StatusBar.java revision e5b770e47d44a40d412c7d42010b2cf67920d9e3
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2010 The Android Open Source Project 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.systemui.statusbar.phone; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.app.StatusBarManager.WINDOW_STATE_SHOWING; 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static android.app.StatusBarManager.windowStateToString; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT; 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.animation.Animator; 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.animation.AnimatorListenerAdapter; 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.annotation.NonNull; 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.ActivityManager; 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.ActivityOptions; 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.Notification; 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.NotificationManager; 420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.PendingIntent; 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.StatusBarManager; 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.admin.DevicePolicyManager; 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.BroadcastReceiver; 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ComponentCallbacks2; 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.ComponentName; 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.IntentFilter; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.IntentSender; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.IPackageManager; 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager; 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Configuration; 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.res.Resources; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.database.ContentObserver; 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.Bitmap; 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.Canvas; 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.ColorFilter; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.PixelFormat; 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.Point; 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.PointF; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.PorterDuff; 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.PorterDuffXfermode; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.Rect; 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.drawable.BitmapDrawable; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.drawable.ColorDrawable; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.graphics.drawable.Drawable; 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.AudioAttributes; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.MediaMetadata; 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.session.MediaController; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.session.MediaSession; 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.session.MediaSessionManager; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.media.session.PlaybackState; 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.metrics.LogMaker; 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.net.Uri; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncTask; 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Bundle; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.IBinder; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.PowerManager; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.RemoteException; 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.ServiceManager; 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemClock; 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties; 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Trace; 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.UserHandle; 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.UserManager; 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Vibrator; 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.provider.Settings; 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.notification.NotificationListenerService.RankingMap; 920825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.notification.StatusBarNotification; 930825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.ArraySet; 940825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.DisplayMetrics; 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.EventLog; 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log; 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.Display; 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.KeyEvent; 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.LayoutInflater; 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.MotionEvent; 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ThreadedRenderer; 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.View; 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ViewGroup; 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ViewParent; 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ViewStub; 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ViewTreeObserver; 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManager; 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.WindowManagerGlobal; 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.animation.AccelerateInterpolator; 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.animation.Interpolator; 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.widget.DateTimeView; 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.widget.ImageView; 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.widget.TextView; 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.logging.MetricsLogger; 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.statusbar.NotificationVisibility; 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.statusbar.StatusBarIcon; 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.util.NotificationMessagingUtil; 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.keyguard.KeyguardHostView.OnDismissAction; 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.keyguard.KeyguardStatusView; 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.keyguard.KeyguardUpdateMonitor; 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.keyguard.KeyguardUpdateMonitorCallback; 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.keyguard.ViewMediatorCallback; 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.ActivityStarterDelegate; 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.DemoMode; 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.Dependency; 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.EventLogTags; 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.Interpolators; 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.Prefs; 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.R; 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.SystemUIFactory; 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.assist.AssistManager; 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.classifier.FalsingLog; 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.classifier.FalsingManager; 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.doze.DozeHost; 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.doze.DozeLog; 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.fragments.FragmentHostManager; 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.fragments.PluginFragmentListener; 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.keyguard.KeyguardViewMediator; 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.qs.QS; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.ActivityStarter; 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeListener; 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeOption; 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.qs.QSFragment; 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.qs.QSPanel; 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.qs.QSTileHost; 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.recents.ScreenPinningRequest; 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.recents.events.EventBus; 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.recents.events.activity.AppTransitionFinishedEvent; 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.recents.events.activity.UndockingTaskEvent; 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.stackdivider.Divider; 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.stackdivider.WindowManagerProxy; 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.ActivatableNotificationView; 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.BackDropView; 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.CommandQueue; 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.DismissView; 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.DragDownHelper; 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.EmptyShadeView; 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.ExpandableNotificationRow; 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.GestureRecorder; 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.KeyboardShortcuts; 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.KeyguardIndicationController; 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationData; 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationData.Entry; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationGuts; 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationInfo; 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationShelf; 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.NotificationSnooze; 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.RemoteInputController; 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.ScrimView; 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.SignalClusterView; 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.StatusBarState; 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.notification.InflationException; 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.notification.VisualStabilityManager; 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.phone.StatusBarIconController.IconManager; 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.BatteryController; 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.BrightnessMirrorController; 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.ConfigurationController; 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.DarkIconDispatcher; 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.DeviceProvisionedController; 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.HeadsUpManager; 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.KeyguardMonitor; 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.KeyguardMonitorImpl; 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.KeyguardUserSwitcher; 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.NetworkController; 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.PreviewInflater; 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.UserInfoController; 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.UserInfoControllerImpl; 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.UserSwitcherController; 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.util.leak.LeakDetector; 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.volume.VolumeComponent; 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.FileDescriptor; 2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.PrintWriter; 2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.StringWriter; 2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Collection; 2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Collections; 2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap; 2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List; 2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Map; 2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.ActivityManager.StackId; 2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.INotificationManager; 2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.KeyguardManager; 2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.NotificationChannel; 2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.RemoteInput; 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.app.TaskStackBuilder; 2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ApplicationInfo; 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager.NameNotFoundException; 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.UserInfo; 2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Build; 2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.dreams.DreamService; 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.dreams.IDreamManager; 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.notification.NotificationListenerService; 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.vr.IVrManager; 2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.service.vr.IVrStateCallbacks; 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.TextUtils; 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Slog; 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.SparseArray; 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.SparseBooleanArray; 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.IWindowManager; 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.ViewAnimationUtils; 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.view.accessibility.AccessibilityManager; 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.widget.RemoteViews; 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.widget.Toast; 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.statusbar.IStatusBarService; 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.widget.LockPatternUtils; 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.DejankUtils; 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.RecentsComponent; 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.SwipeHelper; 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.SystemUI; 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem; 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeGutsContent; 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.recents.Recents; 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.policy.RemoteInputView; 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.statusbar.stack.StackStateAnimator; 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.systemui.util.NotificationChannels; 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashSet; 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Locale; 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Set; 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Stack; 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class StatusBar extends SystemUI implements DemoMode, 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville OnHeadsUpChangedListener, VisualStabilityManager.Callback, SnoozeListener, 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener, 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment, 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ExpandableNotificationRow.OnExpandClickListener { 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean MULTIUSER_DEBUG = false; 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean ENABLE_REMOTE_INPUT = 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SystemProperties.getBoolean("debug.enable_remote_input", true); 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean ENABLE_CHILD_NOTIFICATIONS 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville = SystemProperties.getBoolean("debug.child_notifs", true); 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean FORCE_REMOTE_INPUT_HISTORY = 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SystemProperties.getBoolean("debug.force_remoteinput_history", false); 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false; 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_SHOW_RECENT_APPS = 1019; 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_HIDE_RECENT_APPS = 1020; 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_TOGGLE_RECENTS_APPS = 1021; 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_PRELOAD_RECENT_APPS = 1022; 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023; 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026; 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027; 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final boolean ENABLE_HEADS_UP = true; 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up"; 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Must match constant in Settings. Used to highlight preferences when linking to Settings. 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Should match the values in PhoneWindowManager 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String BANNER_ACTION_CANCEL = 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "com.android.systemui.statusbar.banner_action_cancel"; 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String BANNER_ACTION_SETUP = 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "com.android.systemui.statusbar.banner_action_setup"; 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action"; 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final String TAG = "StatusBar"; 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DEBUG = false; 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean SPEW = false; 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DUMPTRUCK = true; // extra dumpsys info 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DEBUG_GESTURES = false; 3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DEBUG_MEDIA = false; 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false; 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean DEBUG_WINDOW_STATE = false; 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // additional instrumentation for testing purposes; intended to be left on during development 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean CHATTY = DEBUG; 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final String ACTION_FAKE_ARTWORK = "fake_artwork"; 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MSG_CLOSE_PANELS = 1001; 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MSG_OPEN_SETTINGS_PANEL = 1002; 3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // 1020-1040 reserved for BaseStatusBar 3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Time after we abort the launch transition. 3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; 3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; 3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int STATUS_OR_NAV_TRANSIENT = 3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; 3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final long AUTOHIDE_TIMEOUT_MS = 3000; 3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** The minimum delay in ms between reports of notification visibility. */ 3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500; 3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The delay to reset the hint text when the hint animation is finished running. 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int HINT_RESET_DELAY_MS = 1200; 3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville .build(); 3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int FADE_KEYGUARD_START_DELAY = 100; 3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int FADE_KEYGUARD_DURATION = 300; 3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final int FADE_KEYGUARD_DURATION_PULSING = 96; 3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** If true, the system is in the half-boot-to-decryption-screen state. 3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Prudently disable QS and notifications. */ 3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean ONLY_CORE_APPS; 3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** If true, the lockscreen will show a distinct wallpaper */ 3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true; 3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /* If true, the device supports freeform window management. 3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This affects the status bar UI. */ 3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean FREEFORM_WINDOW_MANAGEMENT; 3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * How long to wait before auto-dismissing a notification that was kept for remote input, and 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * these given that they technically don't exist anymore. We wait a bit in case the app issues 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * an update. 3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200; 3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode 3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * won't draw anything and uninitialized memory will show through 3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in 3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * libhwui. 3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final float SRC_MIN_ALPHA = 0.002f; 3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville static { 3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean onlyCoreApps; 3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean freeformWindowManagement; 3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville IPackageManager packageManager = 3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville onlyCoreApps = packageManager.isOnlyCoreApps(); 3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville freeformWindowManagement = packageManager.hasSystemFeature( 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT, 0); 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (RemoteException e) { 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville onlyCoreApps = false; 3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville freeformWindowManagement = false; 3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ONLY_CORE_APPS = onlyCoreApps; 3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville FREEFORM_WINDOW_MANAGEMENT = freeformWindowManagement; 3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville /** 3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The {@link StatusBarState} of the status bar. 3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected int mState; 3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mBouncerShowing; 3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mShowLockscreenNotifications; 3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mAllowLockscreenRemoteInput; 4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PhoneStatusBarPolicy mIconPolicy; 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville VolumeComponent mVolumeComponent; 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville BrightnessMirrorController mBrightnessMirrorController; 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected FingerprintUnlockController mFingerprintUnlockController; 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville LightBarController mLightBarController; 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected LockscreenWallpaper mLockscreenWallpaper; 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mNaturalBarHeight = -1; 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Point mCurrentDisplaySize = new Point(); 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected StatusBarWindowView mStatusBarWindow; 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected PhoneStatusBarView mStatusBarView; 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mStatusBarWindowState = WINDOW_STATE_SHOWING; 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected StatusBarWindowManager mStatusBarWindowManager; 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected UnlockMethodCache mUnlockMethodCache; 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private DozeServiceHost mDozeServiceHost; 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mWakeUpComingFromTouch; 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private PointF mWakeUpTouchLocation; 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mScreenTurningOn; 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mPixelFormat; 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Object mQueueLock = new Object(); 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected StatusBarIconController mIconController; 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // expanded notifications 4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville View mExpandedContents; 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville TextView mNotificationPanelDebugText; 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // settings 4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private QSPanel mQSPanel; 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // top bar 4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected KeyguardStatusBarView mKeyguardStatusBar; 4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville KeyguardStatusView mKeyguardStatusView; 4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville KeyguardBottomAreaView mKeyguardBottomArea; 4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean mLeaveOpenOnKeyguardHide; 4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville KeyguardIndicationController mKeyguardIndicationController; 4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Keyguard is going away soon. 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mKeyguardGoingAway; 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Keyguard is actually fading away now. 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mKeyguardFadingAway; 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected long mKeyguardFadingAwayDelay; 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected long mKeyguardFadingAwayDuration; 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // RemoteInputView to be activated after unlock 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private View mPendingRemoteInputView; 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private View mPendingWorkRemoteInputView; 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private View mReportRejectedTouch; 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mMaxAllowedKeyguardNotifications; 4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean mExpandedVisible; 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // the tracker view 4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mTrackingPosition; // the position of the top of the tracking view. 4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Tracking finger for opening/closing. 4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean mTracking; 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int[] mAbsPos = new int[2]; 4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>(); 4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // for disabling the status bar 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mDisabled1 = 0; 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mDisabled2 = 0; 4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // tracking calls to View.setSystemUiVisibility() 4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final Rect mLastFullscreenStackBounds = new Rect(); 4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final Rect mLastDockedStackBounds = new Rect(); 4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // last value sent to window manager 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE; 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // XXX: gesture research 4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final GestureRecorder mGestureRec = DEBUG_GESTURES 4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ? new GestureRecorder("/sdcard/statusbar_gestures.dat") 4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville : null; 4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ScreenPinningRequest mScreenPinningRequest; 4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ensure quick settings is disabled until the current user makes it through the setup wizard 4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mUserSetup = false; 4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() { 4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onUserSetupChanged() { 4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final boolean userSetup = mDeviceProvisionedController.isUserSetup( 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mDeviceProvisionedController.getCurrentUser()); 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " + 4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville "userSetup=%s mUserSetup=%s", userSetup, mUserSetup)); 4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (userSetup != mUserSetup) { 5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUserSetup = userSetup; 5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mUserSetup && mStatusBarView != null) 5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville animateCollapseQuickSettings(); 5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mKeyguardBottomArea != null) { 5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mKeyguardBottomArea.setUserSetupComplete(mUserSetup); 5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville updateQsExpansionEnabled(); 5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected H mHandler = createHandler(); 5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville final private ContentObserver mHeadsUpObserver = new ContentObserver(mHandler) { 5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onChange(boolean selfChange) { 5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville boolean wasUsing = mUseHeadsUp; 5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt( 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Settings.Global.HEADS_UP_OFF); 5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mHeadsUpTicker = mUseHeadsUp && 0 != Settings.Global.getInt( 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mContext.getContentResolver(), SETTING_HEADS_UP_TICKER, 0); 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled")); 5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (wasUsing != mUseHeadsUp) { 5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mUseHeadsUp) { 5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.d(TAG, "dismissing any existing heads up notification on disable event"); 5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mHeadsUpManager.releaseAllImmediately(); 5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mInteractingWindows; 5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mAutohideSuspended; 5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mStatusBarMode; 5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mMaxKeyguardNotifications; 5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ViewMediatorCallback mKeyguardViewMediatorCallback; 5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected ScrimController mScrimController; 5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected DozeScrimController mDozeScrimController; 5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private final Runnable mAutohide = new Runnable() { 5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void run() { 5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; 5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mSystemUiVisibility != requested) { 5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville notifyUiVisibilityChanged(requested); 5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }}; 5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mWaitingForKeyguardExit; 5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mDozing; 5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mDozingRequested; 5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected boolean mScrimSrcModeEnabled; 5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final Interpolator ALPHA_IN = Interpolators.ALPHA_IN; 5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public static final Interpolator ALPHA_OUT = Interpolators.ALPHA_OUT; 5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected BackDropView mBackdrop; 5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected ImageView mBackdropFront, mBackdropBack; 5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); 5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville protected PorterDuffXfermode mSrcOverXferMode = 5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); 5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private MediaSessionManager mMediaSessionManager; 5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private MediaController mMediaController; 5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private String mMediaNotificationKey; 5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private MediaMetadata mMediaMetadata; 5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private MediaController.Callback mMediaListener 5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville = new MediaController.Callback() { 5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onPlaybackStateChanged(PlaybackState state) { 5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville super.onPlaybackStateChanged(state); 5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); 5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (state != null) { 5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!isPlaybackActive(state.getState())) { 5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville clearCurrentMediaNotification(); 5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville updateMediaMetaData(true, true); 5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void onMetadataChanged(MediaMetadata metadata) { 5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville super.onMetadataChanged(metadata); 5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata); 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mMediaMetadata = metadata; 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville updateMediaMetaData(true, true); 5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville }; 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 592 private final OnChildLocationsChangedListener mOnChildLocationsChangedListener = 593 new OnChildLocationsChangedListener() { 594 @Override 595 public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) { 596 userActivity(); 597 } 598 }; 599 600 private int mDisabledUnmodified1; 601 private int mDisabledUnmodified2; 602 603 /** Keys of notifications currently visible to the user. */ 604 private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications = 605 new ArraySet<>(); 606 private long mLastVisibilityReportUptimeMs; 607 608 private Runnable mLaunchTransitionEndRunnable; 609 protected boolean mLaunchTransitionFadingAway; 610 private ExpandableNotificationRow mDraggedDownRow; 611 private boolean mLaunchCameraOnScreenTurningOn; 612 private boolean mLaunchCameraOnFinishedGoingToSleep; 613 private int mLastCameraLaunchSource; 614 private PowerManager.WakeLock mGestureWakeLock; 615 private Vibrator mVibrator; 616 private long[] mCameraLaunchGestureVibePattern; 617 618 private final int[] mTmpInt2 = new int[2]; 619 620 // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. 621 private int mLastLoggedStateFingerprint; 622 623 /** 624 * If set, the device has started going to sleep but isn't fully non-interactive yet. 625 */ 626 protected boolean mStartedGoingToSleep; 627 628 private final OnChildLocationsChangedListener mNotificationLocationsChangedListener = 629 new OnChildLocationsChangedListener() { 630 @Override 631 public void onChildLocationsChanged( 632 NotificationStackScrollLayout stackScrollLayout) { 633 if (mHandler.hasCallbacks(mVisibilityReporter)) { 634 // Visibilities will be reported when the existing 635 // callback is executed. 636 return; 637 } 638 // Calculate when we're allowed to run the visibility 639 // reporter. Note that this timestamp might already have 640 // passed. That's OK, the callback will just be executed 641 // ASAP. 642 long nextReportUptimeMs = 643 mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS; 644 mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs); 645 } 646 }; 647 648 // Tracks notifications currently visible in mNotificationStackScroller and 649 // emits visibility events via NoMan on changes. 650 private final Runnable mVisibilityReporter = new Runnable() { 651 private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications = 652 new ArraySet<>(); 653 private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications = 654 new ArraySet<>(); 655 private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications = 656 new ArraySet<>(); 657 658 @Override 659 public void run() { 660 mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis(); 661 final String mediaKey = getCurrentMediaNotificationKey(); 662 663 // 1. Loop over mNotificationData entries: 664 // A. Keep list of visible notifications. 665 // B. Keep list of previously hidden, now visible notifications. 666 // 2. Compute no-longer visible notifications by removing currently 667 // visible notifications from the set of previously visible 668 // notifications. 669 // 3. Report newly visible and no-longer visible notifications. 670 // 4. Keep currently visible notifications for next report. 671 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 672 int N = activeNotifications.size(); 673 for (int i = 0; i < N; i++) { 674 Entry entry = activeNotifications.get(i); 675 String key = entry.notification.getKey(); 676 boolean isVisible = mStackScroller.isInVisibleLocation(entry.row); 677 NotificationVisibility visObj = NotificationVisibility.obtain(key, i, isVisible); 678 boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj); 679 if (isVisible) { 680 // Build new set of visible notifications. 681 mTmpCurrentlyVisibleNotifications.add(visObj); 682 if (!previouslyVisible) { 683 mTmpNewlyVisibleNotifications.add(visObj); 684 } 685 } else { 686 // release object 687 visObj.recycle(); 688 } 689 } 690 mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications); 691 mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications); 692 693 logNotificationVisibilityChanges( 694 mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications); 695 696 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications); 697 mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications); 698 699 recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications); 700 mTmpCurrentlyVisibleNotifications.clear(); 701 mTmpNewlyVisibleNotifications.clear(); 702 mTmpNoLongerVisibleNotifications.clear(); 703 } 704 }; 705 706 private NotificationMessagingUtil mMessagingUtil; 707 private KeyguardUserSwitcher mKeyguardUserSwitcher; 708 private UserSwitcherController mUserSwitcherController; 709 private NetworkController mNetworkController; 710 private KeyguardMonitorImpl mKeyguardMonitor; 711 private BatteryController mBatteryController; 712 private boolean mPanelExpanded; 713 private LogMaker mStatusBarStateLog; 714 private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); 715 private NotificationIconAreaController mNotificationIconAreaController; 716 private ConfigurationListener mConfigurationListener; 717 private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException; 718 719 private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) { 720 final int N = array.size(); 721 for (int i = 0 ; i < N; i++) { 722 array.valueAt(i).recycle(); 723 } 724 array.clear(); 725 } 726 727 private final View.OnClickListener mGoToLockedShadeListener = v -> { 728 if (mState == StatusBarState.KEYGUARD) { 729 wakeUpIfDozing(SystemClock.uptimeMillis(), v); 730 goToLockedShade(null); 731 } 732 }; 733 private HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>> mTmpChildOrderMap 734 = new HashMap<>(); 735 private RankingMap mLatestRankingMap; 736 private boolean mNoAnimationOnNextBarModeChange; 737 private FalsingManager mFalsingManager; 738 739 private KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { 740 @Override 741 public void onDreamingStateChanged(boolean dreaming) { 742 if (dreaming) { 743 maybeEscalateHeadsUp(); 744 } 745 } 746 }; 747 748 private NavigationBarFragment mNavigationBar; 749 private View mNavigationBarView; 750 751 @Override 752 public void start() { 753 mNetworkController = Dependency.get(NetworkController.class); 754 mUserSwitcherController = Dependency.get(UserSwitcherController.class); 755 mKeyguardMonitor = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class); 756 mBatteryController = Dependency.get(BatteryController.class); 757 mAssistManager = Dependency.get(AssistManager.class); 758 mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); 759 760 mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 761 mDisplay = mWindowManager.getDefaultDisplay(); 762 updateDisplaySize(); 763 mScrimSrcModeEnabled = mContext.getResources().getBoolean( 764 R.bool.config_status_bar_scrim_behind_use_src); 765 766 DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER)); 767 putComponent(StatusBar.class, this); 768 769 // start old BaseStatusBar.start(). 770 mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); 771 mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService( 772 Context.DEVICE_POLICY_SERVICE); 773 774 mNotificationData = new NotificationData(this); 775 mMessagingUtil = new NotificationMessagingUtil(mContext); 776 777 mAccessibilityManager = (AccessibilityManager) 778 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); 779 780 mDreamManager = IDreamManager.Stub.asInterface( 781 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 782 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 783 784 mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); 785 mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); 786 mContext.getContentResolver().registerContentObserver( 787 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false, 788 mSettingsObserver); 789 mContext.getContentResolver().registerContentObserver( 790 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false, 791 mLockscreenSettingsObserver, 792 UserHandle.USER_ALL); 793 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { 794 mContext.getContentResolver().registerContentObserver( 795 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT), 796 false, 797 mSettingsObserver, 798 UserHandle.USER_ALL); 799 } 800 801 mContext.getContentResolver().registerContentObserver( 802 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), 803 true, 804 mLockscreenSettingsObserver, 805 UserHandle.USER_ALL); 806 807 mBarService = IStatusBarService.Stub.asInterface( 808 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 809 810 mRecents = getComponent(Recents.class); 811 812 final Configuration currentConfig = mContext.getResources().getConfiguration(); 813 mLocale = currentConfig.locale; 814 mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale); 815 816 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 817 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 818 mLockPatternUtils = new LockPatternUtils(mContext); 819 820 // Connect in to the status bar manager service 821 mCommandQueue = getComponent(CommandQueue.class); 822 mCommandQueue.addCallbacks(this); 823 824 int[] switches = new int[9]; 825 ArrayList<IBinder> binders = new ArrayList<IBinder>(); 826 ArrayList<String> iconSlots = new ArrayList<>(); 827 ArrayList<StatusBarIcon> icons = new ArrayList<>(); 828 Rect fullscreenStackBounds = new Rect(); 829 Rect dockedStackBounds = new Rect(); 830 try { 831 mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, 832 fullscreenStackBounds, dockedStackBounds); 833 } catch (RemoteException ex) { 834 // If the system process isn't there we're doomed anyway. 835 } 836 837 createAndAddWindows(); 838 839 mSettingsObserver.onChange(false); // set up 840 mCommandQueue.disable(switches[0], switches[6], false /* animate */); 841 setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff, 842 fullscreenStackBounds, dockedStackBounds); 843 topAppWindowChanged(switches[2] != 0); 844 // StatusBarManagerService has a back up of IME token and it's restored here. 845 setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0); 846 847 // Set up the initial icon state 848 int N = iconSlots.size(); 849 int viewIndex = 0; 850 for (int i=0; i < N; i++) { 851 mCommandQueue.setIcon(iconSlots.get(i), icons.get(i)); 852 } 853 854 // Set up the initial notification state. 855 try { 856 mNotificationListener.registerAsSystemService(mContext, 857 new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()), 858 UserHandle.USER_ALL); 859 } catch (RemoteException e) { 860 Log.e(TAG, "Unable to register notification listener", e); 861 } 862 863 864 if (DEBUG) { 865 Log.d(TAG, String.format( 866 "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x", 867 icons.size(), 868 switches[0], 869 switches[1], 870 switches[2], 871 switches[3] 872 )); 873 } 874 875 mCurrentUserId = ActivityManager.getCurrentUser(); 876 setHeadsUpUser(mCurrentUserId); 877 878 IntentFilter filter = new IntentFilter(); 879 filter.addAction(Intent.ACTION_USER_SWITCHED); 880 filter.addAction(Intent.ACTION_USER_ADDED); 881 filter.addAction(Intent.ACTION_USER_PRESENT); 882 mContext.registerReceiver(mBaseBroadcastReceiver, filter); 883 884 IntentFilter internalFilter = new IntentFilter(); 885 internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); 886 internalFilter.addAction(BANNER_ACTION_CANCEL); 887 internalFilter.addAction(BANNER_ACTION_SETUP); 888 mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null); 889 890 IntentFilter allUsersFilter = new IntentFilter(); 891 allUsersFilter.addAction( 892 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 893 allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED); 894 mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter, 895 null, null); 896 updateCurrentProfilesCache(); 897 898 IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService( 899 Context.VR_SERVICE)); 900 try { 901 vrManager.registerListener(mVrStateCallbacks); 902 } catch (RemoteException e) { 903 Slog.e(TAG, "Failed to register VR mode state listener: " + e); 904 } 905 906 mNonBlockablePkgs = new HashSet<String>(); 907 Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray( 908 com.android.internal.R.array.config_nonBlockableNotificationPackages)); 909 // end old BaseStatusBar.start(). 910 911 mMediaSessionManager 912 = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); 913 // TODO: use MediaSessionManager.SessionListener to hook us up to future updates 914 // in session state 915 916 // Lastly, call to the icon policy to install/update all the icons. 917 mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController); 918 mSettingsObserver.onChange(false); // set up 919 920 mHeadsUpObserver.onChange(true); // set up 921 if (ENABLE_HEADS_UP) { 922 mContext.getContentResolver().registerContentObserver( 923 Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true, 924 mHeadsUpObserver); 925 mContext.getContentResolver().registerContentObserver( 926 Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true, 927 mHeadsUpObserver); 928 } 929 mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); 930 mUnlockMethodCache.addListener(this); 931 startKeyguard(); 932 933 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); 934 mDozeServiceHost = new DozeServiceHost(); 935 putComponent(DozeHost.class, mDozeServiceHost); 936 937 notifyUserAboutHiddenNotifications(); 938 939 mScreenPinningRequest = new ScreenPinningRequest(mContext); 940 mFalsingManager = FalsingManager.getInstance(mContext); 941 942 Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this); 943 944 mConfigurationListener = new ConfigurationListener() { 945 @Override 946 public void onConfigChanged(Configuration newConfig) { 947 StatusBar.this.onConfigurationChanged(newConfig); 948 } 949 950 @Override 951 public void onDensityOrFontScaleChanged() { 952 StatusBar.this.onDensityOrFontScaleChanged(); 953 } 954 }; 955 Dependency.get(ConfigurationController.class).addCallback(mConfigurationListener); 956 } 957 958 protected void createIconController() { 959 } 960 961 // ================================================================================ 962 // Constructing the view 963 // ================================================================================ 964 protected void makeStatusBarView() { 965 final Context context = mContext; 966 updateDisplaySize(); // populates mDisplayMetrics 967 updateResources(); 968 969 inflateStatusBarWindow(context); 970 mStatusBarWindow.setService(this); 971 mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener()); 972 973 // TODO: Deal with the ugliness that comes from having some of the statusbar broken out 974 // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. 975 mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById( 976 R.id.notification_panel); 977 mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( 978 R.id.notification_stack_scroller); 979 mNotificationPanel.setStatusBar(this); 980 mNotificationPanel.setGroupManager(mGroupManager); 981 mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); 982 983 mNotificationIconAreaController = SystemUIFactory.getInstance() 984 .createNotificationIconAreaController(context, this); 985 inflateShelf(); 986 mNotificationIconAreaController.setupShelf(mNotificationShelf); 987 Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController); 988 FragmentHostManager.get(mStatusBarWindow) 989 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { 990 CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment; 991 statusBarFragment.initNotificationIconArea(mNotificationIconAreaController); 992 mStatusBarView = (PhoneStatusBarView) fragment.getView(); 993 mStatusBarView.setBar(this); 994 mStatusBarView.setPanel(mNotificationPanel); 995 mStatusBarView.setScrimController(mScrimController); 996 setAreThereNotifications(); 997 }).getFragmentManager() 998 .beginTransaction() 999 .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) 1000 .commit(); 1001 Dependency.get(StatusBarIconController.class).addIconGroup( 1002 new IconManager((ViewGroup) mKeyguardStatusBar.findViewById(R.id.statusIcons))); 1003 mIconController = Dependency.get(StatusBarIconController.class); 1004 1005 if (!ActivityManager.isHighEndGfx()) { 1006 mStatusBarWindow.setBackground(null); 1007 mNotificationPanel.setBackground(new FastColorDrawable(context.getColor( 1008 R.color.notification_panel_solid_background))); 1009 } 1010 1011 mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager); 1012 mHeadsUpManager.setBar(this); 1013 mHeadsUpManager.addListener(this); 1014 mHeadsUpManager.addListener(mNotificationPanel); 1015 mHeadsUpManager.addListener(mGroupManager); 1016 mHeadsUpManager.addListener(mVisualStabilityManager); 1017 mNotificationPanel.setHeadsUpManager(mHeadsUpManager); 1018 mNotificationData.setHeadsUpManager(mHeadsUpManager); 1019 mGroupManager.setHeadsUpManager(mHeadsUpManager); 1020 mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager); 1021 1022 if (MULTIUSER_DEBUG) { 1023 mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( 1024 R.id.header_debug_info); 1025 mNotificationPanelDebugText.setVisibility(View.VISIBLE); 1026 } 1027 1028 try { 1029 boolean showNav = mWindowManagerService.hasNavigationBar(); 1030 if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); 1031 if (showNav) { 1032 createNavigationBar(); 1033 } 1034 } catch (RemoteException ex) { 1035 // no window manager? good luck with that 1036 } 1037 1038 // figure out which pixel-format to use for the status bar. 1039 mPixelFormat = PixelFormat.OPAQUE; 1040 1041 mStackScroller.setLongPressListener(getNotificationLongClicker()); 1042 mStackScroller.setStatusBar(this); 1043 mStackScroller.setGroupManager(mGroupManager); 1044 mStackScroller.setHeadsUpManager(mHeadsUpManager); 1045 mGroupManager.setOnGroupChangeListener(mStackScroller); 1046 mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller); 1047 1048 inflateEmptyShadeView(); 1049 inflateDismissView(); 1050 mExpandedContents = mStackScroller; 1051 1052 mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop); 1053 mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front); 1054 mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back); 1055 1056 if (ENABLE_LOCKSCREEN_WALLPAPER) { 1057 mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler); 1058 } 1059 1060 mKeyguardStatusView = 1061 (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view); 1062 mKeyguardBottomArea = 1063 (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area); 1064 mKeyguardIndicationController = 1065 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, 1066 (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area), 1067 mKeyguardBottomArea.getLockIcon()); 1068 mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController); 1069 1070 // set the initial view visibility 1071 setAreThereNotifications(); 1072 1073 // TODO: Find better place for this callback. 1074 mBatteryController.addCallback(new BatteryStateChangeCallback() { 1075 @Override 1076 public void onPowerSaveChanged(boolean isPowerSave) { 1077 mHandler.post(mCheckBarModes); 1078 if (mDozeServiceHost != null) { 1079 mDozeServiceHost.firePowerSaveChanged(isPowerSave); 1080 } 1081 } 1082 1083 @Override 1084 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 1085 // noop 1086 } 1087 }); 1088 1089 mLightBarController = new LightBarController(); 1090 if (mNavigationBar != null) { 1091 mNavigationBar.setLightBarController(mLightBarController); 1092 } 1093 1094 ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind); 1095 ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front); 1096 View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim); 1097 mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController, 1098 scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper); 1099 if (mScrimSrcModeEnabled) { 1100 Runnable runnable = new Runnable() { 1101 @Override 1102 public void run() { 1103 boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE; 1104 mScrimController.setDrawBehindAsSrc(asSrc); 1105 mStackScroller.setDrawBackgroundAsSrc(asSrc); 1106 } 1107 }; 1108 mBackdrop.setOnVisibilityChangedRunnable(runnable); 1109 runnable.run(); 1110 } 1111 mHeadsUpManager.addListener(mScrimController); 1112 mStackScroller.setScrimController(mScrimController); 1113 mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller, 1114 mNotificationPanel); 1115 1116 // Other icons 1117 mVolumeComponent = getComponent(VolumeComponent.class); 1118 1119 initEmergencyCryptkeeperText(); 1120 1121 mKeyguardBottomArea.setStatusBar(this); 1122 mKeyguardBottomArea.setUserSetupComplete(mUserSetup); 1123 if (UserManager.get(mContext).isUserSwitcherEnabled()) { 1124 createUserSwitcher(); 1125 } 1126 1127 // Set up the quick settings tile panel 1128 View container = mStatusBarWindow.findViewById(R.id.qs_frame); 1129 if (container != null) { 1130 FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); 1131 fragmentHostManager.getFragmentManager().beginTransaction() 1132 .replace(R.id.qs_frame, new QSFragment(), QS.TAG) 1133 .commit(); 1134 new PluginFragmentListener(container, QS.TAG, QSFragment.class, QS.class) 1135 .startListening(); 1136 final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, 1137 mIconController); 1138 mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow); 1139 fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> { 1140 QS qs = (QS) f; 1141 if (qs instanceof QSFragment) { 1142 ((QSFragment) qs).setHost(qsh); 1143 mQSPanel = ((QSFragment) qs).getQsPanel(); 1144 mQSPanel.setBrightnessMirror(mBrightnessMirrorController); 1145 mKeyguardStatusBar.setQSPanel(mQSPanel); 1146 } 1147 }); 1148 } 1149 1150 mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch); 1151 if (mReportRejectedTouch != null) { 1152 updateReportRejectedTouchVisibility(); 1153 mReportRejectedTouch.setOnClickListener(v -> { 1154 Uri session = mFalsingManager.reportRejectedTouch(); 1155 if (session == null) { return; } 1156 1157 StringWriter message = new StringWriter(); 1158 message.write("Build info: "); 1159 message.write(SystemProperties.get("ro.build.description")); 1160 message.write("\nSerial number: "); 1161 message.write(SystemProperties.get("ro.serialno")); 1162 message.write("\n"); 1163 1164 PrintWriter falsingPw = new PrintWriter(message); 1165 FalsingLog.dump(falsingPw); 1166 falsingPw.flush(); 1167 1168 startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND) 1169 .setType("*/*") 1170 .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report") 1171 .putExtra(Intent.EXTRA_STREAM, session) 1172 .putExtra(Intent.EXTRA_TEXT, message.toString()), 1173 "Share rejected touch report") 1174 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 1175 true /* onlyProvisioned */, true /* dismissShade */); 1176 }); 1177 } 1178 1179 1180 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 1181 if (!pm.isScreenOn()) { 1182 mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); 1183 } 1184 mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, 1185 "GestureWakeLock"); 1186 mVibrator = mContext.getSystemService(Vibrator.class); 1187 int[] pattern = mContext.getResources().getIntArray( 1188 R.array.config_cameraLaunchGestureVibePattern); 1189 mCameraLaunchGestureVibePattern = new long[pattern.length]; 1190 for (int i = 0; i < pattern.length; i++) { 1191 mCameraLaunchGestureVibePattern[i] = pattern[i]; 1192 } 1193 1194 // receive broadcasts 1195 IntentFilter filter = new IntentFilter(); 1196 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 1197 filter.addAction(Intent.ACTION_SCREEN_OFF); 1198 filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); 1199 context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 1200 1201 IntentFilter demoFilter = new IntentFilter(); 1202 if (DEBUG_MEDIA_FAKE_ARTWORK) { 1203 demoFilter.addAction(ACTION_FAKE_ARTWORK); 1204 } 1205 demoFilter.addAction(ACTION_DEMO); 1206 context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, 1207 android.Manifest.permission.DUMP, null); 1208 1209 // listen for USER_SETUP_COMPLETE setting (per-user) 1210 mDeviceProvisionedController.addCallback(mUserSetupObserver); 1211 mUserSetupObserver.onUserSetupChanged(); 1212 1213 // disable profiling bars, since they overlap and clutter the output on app windows 1214 ThreadedRenderer.overrideProperty("disableProfileBars", "true"); 1215 1216 // Private API call to make the shadows look better for Recents 1217 ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); 1218 } 1219 1220 protected void createNavigationBar() { 1221 mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> { 1222 mNavigationBar = (NavigationBarFragment) fragment; 1223 if (mLightBarController != null) { 1224 mNavigationBar.setLightBarController(mLightBarController); 1225 } 1226 mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility); 1227 }); 1228 } 1229 1230 private void initEmergencyCryptkeeperText() { 1231 View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text); 1232 if (mNetworkController.hasEmergencyCryptKeeperText()) { 1233 if (emergencyViewStub != null) { 1234 ((ViewStub) emergencyViewStub).inflate(); 1235 } 1236 mNetworkController.addCallback(new NetworkController.SignalCallback() { 1237 @Override 1238 public void setIsAirplaneMode(NetworkController.IconState icon) { 1239 recomputeDisableFlags(true /* animate */); 1240 } 1241 }); 1242 } else if (emergencyViewStub != null) { 1243 ViewGroup parent = (ViewGroup) emergencyViewStub.getParent(); 1244 parent.removeView(emergencyViewStub); 1245 } 1246 } 1247 1248 /** 1249 * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the 1250 * background window of the status bar is clicked. 1251 */ 1252 protected View.OnTouchListener getStatusBarWindowTouchListener() { 1253 return (v, event) -> { 1254 checkUserAutohide(v, event); 1255 checkRemoteInputOutside(event); 1256 if (event.getAction() == MotionEvent.ACTION_DOWN) { 1257 if (mExpandedVisible) { 1258 animateCollapsePanels(); 1259 } 1260 } 1261 return mStatusBarWindow.onTouchEvent(event); 1262 }; 1263 } 1264 1265 private void inflateShelf() { 1266 mNotificationShelf = 1267 (NotificationShelf) LayoutInflater.from(mContext).inflate( 1268 R.layout.status_bar_notification_shelf, mStackScroller, false); 1269 mNotificationShelf.setOnActivatedListener(this); 1270 mStackScroller.setShelf(mNotificationShelf); 1271 mNotificationShelf.setOnClickListener(mGoToLockedShadeListener); 1272 mNotificationShelf.setStatusBarState(mState); 1273 } 1274 1275 protected void onDensityOrFontScaleChanged() { 1276 // start old BaseStatusBar.onDensityOrFontScaleChanged(). 1277 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 1278 for (int i = 0; i < activeNotifications.size(); i++) { 1279 Entry entry = activeNotifications.get(i); 1280 boolean exposedGuts = mNotificationGutsExposed != null 1281 && entry.row.getGuts() == mNotificationGutsExposed; 1282 entry.row.onDensityOrFontScaleChanged(); 1283 if (exposedGuts) { 1284 mNotificationGutsExposed = entry.row.getGuts(); 1285 bindGuts(entry.row, mGutsMenuItem); 1286 } 1287 } 1288 // end old BaseStatusBar.onDensityOrFontScaleChanged(). 1289 mScrimController.onDensityOrFontScaleChanged(); 1290 // TODO: Remove this. 1291 if (mStatusBarView != null) mStatusBarView.onDensityOrFontScaleChanged(); 1292 if (mBrightnessMirrorController != null) { 1293 mBrightnessMirrorController.onDensityOrFontScaleChanged(); 1294 } 1295 inflateSignalClusters(); 1296 mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext); 1297 inflateDismissView(); 1298 updateClearAll(); 1299 inflateEmptyShadeView(); 1300 updateEmptyShadeView(); 1301 mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged(); 1302 // TODO: Bring these out of StatusBar. 1303 ((UserInfoControllerImpl) Dependency.get(UserInfoController.class)) 1304 .onDensityOrFontScaleChanged(); 1305 Dependency.get(UserSwitcherController.class).onDensityOrFontScaleChanged(); 1306 if (mKeyguardUserSwitcher != null) { 1307 mKeyguardUserSwitcher.onDensityOrFontScaleChanged(); 1308 } 1309 } 1310 1311 private void inflateSignalClusters() { 1312 reinflateSignalCluster(mKeyguardStatusBar); 1313 } 1314 1315 public static SignalClusterView reinflateSignalCluster(View view) { 1316 Context context = view.getContext(); 1317 SignalClusterView signalCluster = 1318 (SignalClusterView) view.findViewById(R.id.signal_cluster); 1319 if (signalCluster != null) { 1320 ViewParent parent = signalCluster.getParent(); 1321 if (parent instanceof ViewGroup) { 1322 ViewGroup viewParent = (ViewGroup) parent; 1323 int index = viewParent.indexOfChild(signalCluster); 1324 viewParent.removeView(signalCluster); 1325 SignalClusterView newCluster = (SignalClusterView) LayoutInflater.from(context) 1326 .inflate(R.layout.signal_cluster_view, viewParent, false); 1327 ViewGroup.MarginLayoutParams layoutParams = 1328 (ViewGroup.MarginLayoutParams) viewParent.getLayoutParams(); 1329 layoutParams.setMarginsRelative( 1330 context.getResources().getDimensionPixelSize( 1331 R.dimen.signal_cluster_margin_start), 1332 0, 0, 0); 1333 newCluster.setLayoutParams(layoutParams); 1334 viewParent.addView(newCluster, index); 1335 return newCluster; 1336 } 1337 return signalCluster; 1338 } 1339 return null; 1340 } 1341 1342 private void inflateEmptyShadeView() { 1343 mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( 1344 R.layout.status_bar_no_notifications, mStackScroller, false); 1345 mStackScroller.setEmptyShadeView(mEmptyShadeView); 1346 } 1347 1348 private void inflateDismissView() { 1349 mDismissView = (DismissView) LayoutInflater.from(mContext).inflate( 1350 R.layout.status_bar_notification_dismiss_all, mStackScroller, false); 1351 mDismissView.setOnButtonClickListener(new View.OnClickListener() { 1352 @Override 1353 public void onClick(View v) { 1354 MetricsLogger.action(mContext, MetricsEvent.ACTION_DISMISS_ALL_NOTES); 1355 clearAllNotifications(); 1356 } 1357 }); 1358 mStackScroller.setDismissView(mDismissView); 1359 } 1360 1361 protected void createUserSwitcher() { 1362 mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, 1363 (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), 1364 mKeyguardStatusBar, mNotificationPanel); 1365 } 1366 1367 protected void inflateStatusBarWindow(Context context) { 1368 mStatusBarWindow = (StatusBarWindowView) View.inflate(context, 1369 R.layout.super_status_bar, null); 1370 } 1371 1372 public void clearAllNotifications() { 1373 1374 // animate-swipe all dismissable notifications, then animate the shade closed 1375 int numChildren = mStackScroller.getChildCount(); 1376 1377 final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren); 1378 for (int i = 0; i < numChildren; i++) { 1379 final View child = mStackScroller.getChildAt(i); 1380 if (child instanceof ExpandableNotificationRow) { 1381 if (mStackScroller.canChildBeDismissed(child)) { 1382 if (child.getVisibility() == View.VISIBLE) { 1383 viewsToHide.add(child); 1384 } 1385 } 1386 ExpandableNotificationRow row = (ExpandableNotificationRow) child; 1387 List<ExpandableNotificationRow> children = row.getNotificationChildren(); 1388 if (row.areChildrenExpanded() && children != null) { 1389 for (ExpandableNotificationRow childRow : children) { 1390 if (mStackScroller.canChildBeDismissed(childRow)) { 1391 if (childRow.getVisibility() == View.VISIBLE) { 1392 viewsToHide.add(childRow); 1393 } 1394 } 1395 } 1396 } 1397 } 1398 } 1399 if (viewsToHide.isEmpty()) { 1400 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 1401 return; 1402 } 1403 1404 addPostCollapseAction(new Runnable() { 1405 @Override 1406 public void run() { 1407 mStackScroller.setDismissAllInProgress(false); 1408 try { 1409 mBarService.onClearAllNotifications(mCurrentUserId); 1410 } catch (Exception ex) { } 1411 } 1412 }); 1413 1414 performDismissAllAnimations(viewsToHide); 1415 1416 } 1417 1418 private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) { 1419 Runnable animationFinishAction = new Runnable() { 1420 @Override 1421 public void run() { 1422 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 1423 } 1424 }; 1425 1426 // let's disable our normal animations 1427 mStackScroller.setDismissAllInProgress(true); 1428 1429 // Decrease the delay for every row we animate to give the sense of 1430 // accelerating the swipes 1431 int rowDelayDecrement = 10; 1432 int currentDelay = 140; 1433 int totalDelay = 180; 1434 int numItems = hideAnimatedList.size(); 1435 for (int i = numItems - 1; i >= 0; i--) { 1436 View view = hideAnimatedList.get(i); 1437 Runnable endRunnable = null; 1438 if (i == 0) { 1439 endRunnable = animationFinishAction; 1440 } 1441 mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260); 1442 currentDelay = Math.max(50, currentDelay - rowDelayDecrement); 1443 totalDelay += currentDelay; 1444 } 1445 } 1446 1447 protected void setZenMode(int mode) { 1448 // start old BaseStatusBar.setZenMode(). 1449 if (isDeviceProvisioned()) { 1450 mZenMode = mode; 1451 updateNotifications(); 1452 } 1453 // end old BaseStatusBar.setZenMode(). 1454 } 1455 1456 protected void startKeyguard() { 1457 Trace.beginSection("StatusBar#startKeyguard"); 1458 KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); 1459 mFingerprintUnlockController = new FingerprintUnlockController(mContext, 1460 mDozeScrimController, keyguardViewMediator, 1461 mScrimController, this, UnlockMethodCache.getInstance(mContext)); 1462 mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, 1463 getBouncerContainer(), mScrimController, 1464 mFingerprintUnlockController); 1465 mKeyguardIndicationController.setStatusBarKeyguardViewManager( 1466 mStatusBarKeyguardViewManager); 1467 mKeyguardIndicationController.setUserInfoController( 1468 Dependency.get(UserInfoController.class)); 1469 mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); 1470 mRemoteInputController.addCallback(mStatusBarKeyguardViewManager); 1471 1472 mRemoteInputController.addCallback(new RemoteInputController.Callback() { 1473 @Override 1474 public void onRemoteInputSent(Entry entry) { 1475 if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) { 1476 removeNotification(entry.key, null); 1477 } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) { 1478 // We're currently holding onto this notification, but from the apps point of 1479 // view it is already canceled, so we'll need to cancel it on the apps behalf 1480 // after sending - unless the app posts an update in the mean time, so wait a 1481 // bit. 1482 mHandler.postDelayed(() -> { 1483 if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) { 1484 removeNotification(entry.key, null); 1485 } 1486 }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY); 1487 } 1488 } 1489 }); 1490 1491 mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); 1492 mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController); 1493 Trace.endSection(); 1494 } 1495 1496 protected View getStatusBarView() { 1497 return mStatusBarView; 1498 } 1499 1500 public StatusBarWindowView getStatusBarWindow() { 1501 return mStatusBarWindow; 1502 } 1503 1504 protected ViewGroup getBouncerContainer() { 1505 return mStatusBarWindow; 1506 } 1507 1508 public int getStatusBarHeight() { 1509 if (mNaturalBarHeight < 0) { 1510 final Resources res = mContext.getResources(); 1511 mNaturalBarHeight = 1512 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 1513 } 1514 return mNaturalBarHeight; 1515 } 1516 1517 protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) { 1518 if (mRecents == null) { 1519 return false; 1520 } 1521 int dockSide = WindowManagerProxy.getInstance().getDockSide(); 1522 if (dockSide == WindowManager.DOCKED_INVALID) { 1523 return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, 1524 ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction); 1525 } else { 1526 Divider divider = getComponent(Divider.class); 1527 if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) { 1528 // Undocking from the minimized state is not supported 1529 return false; 1530 } else { 1531 EventBus.getDefault().send(new UndockingTaskEvent()); 1532 if (metricsUndockAction != -1) { 1533 MetricsLogger.action(mContext, metricsUndockAction); 1534 } 1535 } 1536 } 1537 return true; 1538 } 1539 1540 void awakenDreams() { 1541 if (mDreamManager != null) { 1542 try { 1543 mDreamManager.awaken(); 1544 } catch (RemoteException e) { 1545 // fine, stay asleep then 1546 } 1547 } 1548 } 1549 1550 public UserHandle getCurrentUserHandle() { 1551 return new UserHandle(mCurrentUserId); 1552 } 1553 1554 public void addNotification(StatusBarNotification notification, RankingMap ranking, 1555 Entry oldEntry) throws InflationException { 1556 if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); 1557 1558 mNotificationData.updateRanking(ranking); 1559 Entry shadeEntry = createNotificationViews(notification); 1560 boolean isHeadsUped = shouldPeek(shadeEntry); 1561 if (isHeadsUped) { 1562 mHeadsUpManager.showNotification(shadeEntry); 1563 // Mark as seen immediately 1564 setNotificationShown(notification); 1565 } 1566 1567 if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) { 1568 if (shouldSuppressFullScreenIntent(notification.getKey())) { 1569 if (DEBUG) { 1570 Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey()); 1571 } 1572 } else if (mNotificationData.getImportance(notification.getKey()) 1573 < NotificationManager.IMPORTANCE_HIGH) { 1574 if (DEBUG) { 1575 Log.d(TAG, "No Fullscreen intent: not important enough: " 1576 + notification.getKey()); 1577 } 1578 } else { 1579 // Stop screensaver if the notification has a full-screen intent. 1580 // (like an incoming phone call) 1581 awakenDreams(); 1582 1583 // not immersive & a full-screen alert should be shown 1584 if (DEBUG) 1585 Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); 1586 try { 1587 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, 1588 notification.getKey()); 1589 notification.getNotification().fullScreenIntent.send(); 1590 shadeEntry.notifyFullScreenIntentLaunched(); 1591 MetricsLogger.count(mContext, "note_fullscreen", 1); 1592 } catch (PendingIntent.CanceledException e) { 1593 } 1594 } 1595 } 1596 addNotificationViews(shadeEntry, ranking); 1597 // Recalculate the position of the sliding windows and the titles. 1598 setAreThereNotifications(); 1599 } 1600 1601 public void handleInflationException(StatusBarNotification notification, InflationException e) { 1602 handleNotificationError(notification, e.getMessage()); 1603 } 1604 1605 private boolean shouldSuppressFullScreenIntent(String key) { 1606 if (isDeviceInVrMode()) { 1607 return true; 1608 } 1609 1610 if (mPowerManager.isInteractive()) { 1611 return mNotificationData.shouldSuppressScreenOn(key); 1612 } else { 1613 return mNotificationData.shouldSuppressScreenOff(key); 1614 } 1615 } 1616 1617 protected void updateNotificationRanking(RankingMap ranking) { 1618 mNotificationData.updateRanking(ranking); 1619 updateNotifications(); 1620 } 1621 1622 public void removeNotification(String key, RankingMap ranking) { 1623 boolean deferRemoval = false; 1624 if (mHeadsUpManager.isHeadsUp(key)) { 1625 // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the 1626 // sending look longer than it takes. 1627 // Also we should not defer the removal if reordering isn't allowed since otherwise 1628 // some notifications can't disappear before the panel is closed. 1629 boolean ignoreEarliestRemovalTime = mRemoteInputController.isSpinning(key) 1630 && !FORCE_REMOTE_INPUT_HISTORY 1631 || !mVisualStabilityManager.isReorderingAllowed(); 1632 deferRemoval = !mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime); 1633 } 1634 if (key.equals(mMediaNotificationKey)) { 1635 clearCurrentMediaNotification(); 1636 updateMediaMetaData(true, true); 1637 } 1638 if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputController.isSpinning(key)) { 1639 Entry entry = mNotificationData.get(key); 1640 StatusBarNotification sbn = entry.notification; 1641 1642 Notification.Builder b = Notification.Builder 1643 .recoverBuilder(mContext, sbn.getNotification().clone()); 1644 CharSequence[] oldHistory = sbn.getNotification().extras 1645 .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); 1646 CharSequence[] newHistory; 1647 if (oldHistory == null) { 1648 newHistory = new CharSequence[1]; 1649 } else { 1650 newHistory = new CharSequence[oldHistory.length + 1]; 1651 for (int i = 0; i < oldHistory.length; i++) { 1652 newHistory[i + 1] = oldHistory[i]; 1653 } 1654 } 1655 newHistory[0] = String.valueOf(entry.remoteInputText); 1656 b.setRemoteInputHistory(newHistory); 1657 1658 Notification newNotification = b.build(); 1659 1660 // Undo any compatibility view inflation 1661 newNotification.contentView = sbn.getNotification().contentView; 1662 newNotification.bigContentView = sbn.getNotification().bigContentView; 1663 newNotification.headsUpContentView = sbn.getNotification().headsUpContentView; 1664 1665 StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(), 1666 sbn.getOpPkg(), 1667 sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), 1668 newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime()); 1669 boolean updated = false; 1670 try { 1671 updateNotification(newSbn, null); 1672 updated = true; 1673 } catch (InflationException e) { 1674 deferRemoval = false; 1675 } 1676 if (updated) { 1677 mKeysKeptForRemoteInput.add(entry.key); 1678 return; 1679 } 1680 } 1681 if (deferRemoval) { 1682 mLatestRankingMap = ranking; 1683 mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); 1684 return; 1685 } 1686 Entry entry = mNotificationData.get(key); 1687 1688 if (entry != null && mRemoteInputController.isRemoteInputActive(entry) 1689 && (entry.row != null && !entry.row.isDismissed())) { 1690 mLatestRankingMap = ranking; 1691 mRemoteInputEntriesToRemoveOnCollapse.add(entry); 1692 return; 1693 } 1694 1695 if (entry != null && entry.row != null) { 1696 entry.row.setRemoved(); 1697 mStackScroller.cleanUpViewState(entry.row); 1698 } 1699 // Let's remove the children if this was a summary 1700 handleGroupSummaryRemoved(key, ranking); 1701 StatusBarNotification old = removeNotificationViews(key, ranking); 1702 if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); 1703 1704 if (old != null) { 1705 if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() 1706 && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) { 1707 if (mState == StatusBarState.SHADE) { 1708 animateCollapsePanels(); 1709 } else if (mState == StatusBarState.SHADE_LOCKED && !isCollapsing()) { 1710 goToKeyguard(); 1711 } 1712 } 1713 } 1714 setAreThereNotifications(); 1715 } 1716 1717 /** 1718 * Ensures that the group children are cancelled immediately when the group summary is cancelled 1719 * instead of waiting for the notification manager to send all cancels. Otherwise this could 1720 * lead to flickers. 1721 * 1722 * This also ensures that the animation looks nice and only consists of a single disappear 1723 * animation instead of multiple. 1724 * 1725 * @param key the key of the notification was removed 1726 * @param ranking the current ranking 1727 */ 1728 private void handleGroupSummaryRemoved(String key, 1729 RankingMap ranking) { 1730 Entry entry = mNotificationData.get(key); 1731 if (entry != null && entry.row != null 1732 && entry.row.isSummaryWithChildren()) { 1733 if (entry.notification.getOverrideGroupKey() != null && !entry.row.isDismissed()) { 1734 // We don't want to remove children for autobundled notifications as they are not 1735 // always cancelled. We only remove them if they were dismissed by the user. 1736 return; 1737 } 1738 List<ExpandableNotificationRow> notificationChildren = 1739 entry.row.getNotificationChildren(); 1740 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>(); 1741 for (int i = 0; i < notificationChildren.size(); i++) { 1742 ExpandableNotificationRow row = notificationChildren.get(i); 1743 if ((row.getStatusBarNotification().getNotification().flags 1744 & Notification.FLAG_FOREGROUND_SERVICE) != 0) { 1745 // the child is a forground service notification which we can't remove! 1746 continue; 1747 } 1748 toRemove.add(row); 1749 toRemove.get(i).setKeepInParent(true); 1750 // we need to set this state earlier as otherwise we might generate some weird 1751 // animations 1752 toRemove.get(i).setRemoved(); 1753 } 1754 } 1755 } 1756 1757 protected void performRemoveNotification(StatusBarNotification n) { 1758 Entry entry = mNotificationData.get(n.getKey()); 1759 if (mRemoteInputController.isRemoteInputActive(entry)) { 1760 mRemoteInputController.removeRemoteInput(entry, null); 1761 } 1762 // start old BaseStatusBar.performRemoveNotification. 1763 final String pkg = n.getPackageName(); 1764 final String tag = n.getTag(); 1765 final int id = n.getId(); 1766 final int userId = n.getUserId(); 1767 try { 1768 mBarService.onNotificationClear(pkg, tag, id, userId); 1769 if (FORCE_REMOTE_INPUT_HISTORY 1770 && mKeysKeptForRemoteInput.contains(n.getKey())) { 1771 mKeysKeptForRemoteInput.remove(n.getKey()); 1772 } 1773 removeNotification(n.getKey(), null); 1774 1775 } catch (RemoteException ex) { 1776 // system process is dead if we're here. 1777 } 1778 // end old BaseStatusBar.performRemoveNotification. 1779 } 1780 1781 private void updateNotificationShade() { 1782 if (mStackScroller == null) return; 1783 1784 // Do not modify the notifications during collapse. 1785 if (isCollapsing()) { 1786 addPostCollapseAction(new Runnable() { 1787 @Override 1788 public void run() { 1789 updateNotificationShade(); 1790 } 1791 }); 1792 return; 1793 } 1794 1795 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 1796 ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size()); 1797 final int N = activeNotifications.size(); 1798 for (int i=0; i<N; i++) { 1799 Entry ent = activeNotifications.get(i); 1800 if (ent.row.isDismissed() || ent.row.isRemoved()) { 1801 // we don't want to update removed notifications because they could 1802 // temporarily become children if they were isolated before. 1803 continue; 1804 } 1805 int vis = ent.notification.getNotification().visibility; 1806 int userId = ent.notification.getUserId(); 1807 1808 // Display public version of the notification if we need to redact. 1809 boolean deviceSensitive = (isLockscreenPublicMode(mCurrentUserId) 1810 && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)); 1811 boolean userSensitive = deviceSensitive || (isLockscreenPublicMode(userId) 1812 && !userAllowsPrivateNotificationsInPublic(userId)); 1813 boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE; 1814 boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey()); 1815 boolean sensitive = (sensitiveNote && userSensitive) || sensitivePackage; 1816 boolean showingPublic = sensitive && isLockscreenPublicMode(userId); 1817 if (showingPublic) { 1818 updatePublicContentView(ent, ent.notification); 1819 } 1820 ent.row.setSensitive(sensitive, deviceSensitive); 1821 if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) { 1822 ExpandableNotificationRow summary = mGroupManager.getGroupSummary( 1823 ent.row.getStatusBarNotification()); 1824 List<ExpandableNotificationRow> orderedChildren = 1825 mTmpChildOrderMap.get(summary); 1826 if (orderedChildren == null) { 1827 orderedChildren = new ArrayList<>(); 1828 mTmpChildOrderMap.put(summary, orderedChildren); 1829 } 1830 orderedChildren.add(ent.row); 1831 } else { 1832 toShow.add(ent.row); 1833 } 1834 1835 } 1836 1837 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>(); 1838 for (int i=0; i< mStackScroller.getChildCount(); i++) { 1839 View child = mStackScroller.getChildAt(i); 1840 if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) { 1841 toRemove.add((ExpandableNotificationRow) child); 1842 } 1843 } 1844 1845 for (ExpandableNotificationRow remove : toRemove) { 1846 if (mGroupManager.isChildInGroupWithSummary(remove.getStatusBarNotification())) { 1847 // we are only transfering this notification to its parent, don't generate an animation 1848 mStackScroller.setChildTransferInProgress(true); 1849 } 1850 if (remove.isSummaryWithChildren()) { 1851 remove.removeAllChildren(); 1852 } 1853 mStackScroller.removeView(remove); 1854 mStackScroller.setChildTransferInProgress(false); 1855 } 1856 1857 removeNotificationChildren(); 1858 1859 for (int i=0; i<toShow.size(); i++) { 1860 View v = toShow.get(i); 1861 if (v.getParent() == null) { 1862 mVisualStabilityManager.notifyViewAddition(v); 1863 mStackScroller.addView(v); 1864 } 1865 } 1866 1867 addNotificationChildrenAndSort(); 1868 1869 // So after all this work notifications still aren't sorted correctly. 1870 // Let's do that now by advancing through toShow and mStackScroller in 1871 // lock-step, making sure mStackScroller matches what we see in toShow. 1872 int j = 0; 1873 for (int i = 0; i < mStackScroller.getChildCount(); i++) { 1874 View child = mStackScroller.getChildAt(i); 1875 if (!(child instanceof ExpandableNotificationRow)) { 1876 // We don't care about non-notification views. 1877 continue; 1878 } 1879 1880 ExpandableNotificationRow targetChild = toShow.get(j); 1881 if (child != targetChild) { 1882 // Oops, wrong notification at this position. Put the right one 1883 // here and advance both lists. 1884 if (mVisualStabilityManager.canReorderNotification(targetChild)) { 1885 mStackScroller.changeViewPosition(targetChild, i); 1886 } else { 1887 mVisualStabilityManager.addReorderingAllowedCallback(this); 1888 } 1889 } 1890 j++; 1891 1892 } 1893 1894 mVisualStabilityManager.onReorderingFinished(); 1895 // clear the map again for the next usage 1896 mTmpChildOrderMap.clear(); 1897 1898 updateRowStates(); 1899 updateSpeedBumpIndex(); 1900 updateClearAll(); 1901 updateEmptyShadeView(); 1902 1903 updateQsExpansionEnabled(); 1904 1905 // Let's also update the icons 1906 mNotificationIconAreaController.updateNotificationIcons(mNotificationData); 1907 } 1908 1909 /** 1910 * Disable QS if device not provisioned. 1911 * If the user switcher is simple then disable QS during setup because 1912 * the user intends to use the lock screen user switcher, QS in not needed. 1913 */ 1914 private void updateQsExpansionEnabled() { 1915 mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() 1916 && (mUserSetup || mUserSwitcherController == null 1917 || !mUserSwitcherController.isSimpleUserSwitcher()) 1918 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) 1919 && !ONLY_CORE_APPS); 1920 } 1921 1922 private void addNotificationChildrenAndSort() { 1923 // Let's now add all notification children which are missing 1924 boolean orderChanged = false; 1925 for (int i = 0; i < mStackScroller.getChildCount(); i++) { 1926 View view = mStackScroller.getChildAt(i); 1927 if (!(view instanceof ExpandableNotificationRow)) { 1928 // We don't care about non-notification views. 1929 continue; 1930 } 1931 1932 ExpandableNotificationRow parent = (ExpandableNotificationRow) view; 1933 List<ExpandableNotificationRow> children = parent.getNotificationChildren(); 1934 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent); 1935 1936 for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size(); 1937 childIndex++) { 1938 ExpandableNotificationRow childView = orderedChildren.get(childIndex); 1939 if (children == null || !children.contains(childView)) { 1940 if (childView.getParent() != null) { 1941 Log.wtf(TAG, "trying to add a notification child that already has " + 1942 "a parent. class:" + childView.getParent().getClass() + 1943 "\n child: " + childView); 1944 // This shouldn't happen. We can recover by removing it though. 1945 ((ViewGroup) childView.getParent()).removeView(childView); 1946 } 1947 mVisualStabilityManager.notifyViewAddition(childView); 1948 parent.addChildNotification(childView, childIndex); 1949 mStackScroller.notifyGroupChildAdded(childView); 1950 } 1951 } 1952 1953 // Finally after removing and adding has been beformed we can apply the order. 1954 orderChanged |= parent.applyChildOrder(orderedChildren, mVisualStabilityManager, this); 1955 } 1956 if (orderChanged) { 1957 mStackScroller.generateChildOrderChangedEvent(); 1958 } 1959 } 1960 1961 private void removeNotificationChildren() { 1962 // First let's remove all children which don't belong in the parents 1963 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>(); 1964 for (int i = 0; i < mStackScroller.getChildCount(); i++) { 1965 View view = mStackScroller.getChildAt(i); 1966 if (!(view instanceof ExpandableNotificationRow)) { 1967 // We don't care about non-notification views. 1968 continue; 1969 } 1970 1971 ExpandableNotificationRow parent = (ExpandableNotificationRow) view; 1972 List<ExpandableNotificationRow> children = parent.getNotificationChildren(); 1973 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent); 1974 1975 if (children != null) { 1976 toRemove.clear(); 1977 for (ExpandableNotificationRow childRow : children) { 1978 if ((orderedChildren == null 1979 || !orderedChildren.contains(childRow)) 1980 && !childRow.keepInParent()) { 1981 toRemove.add(childRow); 1982 } 1983 } 1984 for (ExpandableNotificationRow remove : toRemove) { 1985 parent.removeChildNotification(remove); 1986 if (mNotificationData.get(remove.getStatusBarNotification().getKey()) == null) { 1987 // We only want to add an animation if the view is completely removed 1988 // otherwise it's just a transfer 1989 mStackScroller.notifyGroupChildRemoved(remove, 1990 parent.getChildrenContainer()); 1991 } 1992 } 1993 } 1994 } 1995 } 1996 1997 public void addQsTile(ComponentName tile) { 1998 mQSPanel.getHost().addTile(tile); 1999 } 2000 2001 public void remQsTile(ComponentName tile) { 2002 mQSPanel.getHost().removeTile(tile); 2003 } 2004 2005 public void clickTile(ComponentName tile) { 2006 mQSPanel.clickTile(tile); 2007 } 2008 2009 private boolean packageHasVisibilityOverride(String key) { 2010 return mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_PRIVATE; 2011 } 2012 2013 private void updateClearAll() { 2014 boolean showDismissView = 2015 mState != StatusBarState.KEYGUARD && 2016 hasActiveClearableNotifications(); 2017 mStackScroller.updateDismissView(showDismissView); 2018 } 2019 2020 /** 2021 * Return whether there are any clearable notifications 2022 */ 2023 private boolean hasActiveClearableNotifications() { 2024 int childCount = mStackScroller.getChildCount(); 2025 for (int i = 0; i < childCount; i++) { 2026 View child = mStackScroller.getChildAt(i); 2027 if (!(child instanceof ExpandableNotificationRow)) { 2028 continue; 2029 } 2030 if (((ExpandableNotificationRow) child).canViewBeDismissed()) { 2031 return true; 2032 } 2033 } 2034 return false; 2035 } 2036 2037 private void updateEmptyShadeView() { 2038 boolean showEmptyShadeView = 2039 mState != StatusBarState.KEYGUARD && 2040 mNotificationData.getActiveNotifications().size() == 0; 2041 mNotificationPanel.showEmptyShadeView(showEmptyShadeView); 2042 } 2043 2044 private void updateSpeedBumpIndex() { 2045 int speedBumpIndex = 0; 2046 int currentIndex = 0; 2047 final int N = mStackScroller.getChildCount(); 2048 for (int i = 0; i < N; i++) { 2049 View view = mStackScroller.getChildAt(i); 2050 if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) { 2051 continue; 2052 } 2053 ExpandableNotificationRow row = (ExpandableNotificationRow) view; 2054 currentIndex++; 2055 if (!mNotificationData.isAmbient(row.getStatusBarNotification().getKey())) { 2056 speedBumpIndex = currentIndex; 2057 } 2058 } 2059 boolean noAmbient = speedBumpIndex == N; 2060 mStackScroller.updateSpeedBumpIndex(speedBumpIndex, noAmbient); 2061 } 2062 2063 public static boolean isTopLevelChild(Entry entry) { 2064 return entry.row.getParent() instanceof NotificationStackScrollLayout; 2065 } 2066 2067 protected void updateNotifications() { 2068 mNotificationData.filterAndSort(); 2069 2070 updateNotificationShade(); 2071 } 2072 2073 public void requestNotificationUpdate() { 2074 updateNotifications(); 2075 } 2076 2077 protected void setAreThereNotifications() { 2078 2079 if (SPEW) { 2080 final boolean clearable = hasActiveNotifications() && 2081 hasActiveClearableNotifications(); 2082 Log.d(TAG, "setAreThereNotifications: N=" + 2083 mNotificationData.getActiveNotifications().size() + " any=" + 2084 hasActiveNotifications() + " clearable=" + clearable); 2085 } 2086 2087 if (mStatusBarView != null) { 2088 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); 2089 final boolean showDot = hasActiveNotifications() && !areLightsOn(); 2090 if (showDot != (nlo.getAlpha() == 1.0f)) { 2091 if (showDot) { 2092 nlo.setAlpha(0f); 2093 nlo.setVisibility(View.VISIBLE); 2094 } 2095 nlo.animate() 2096 .alpha(showDot ? 1 : 0) 2097 .setDuration(showDot ? 750 : 250) 2098 .setInterpolator(new AccelerateInterpolator(2.0f)) 2099 .setListener(showDot ? null : new AnimatorListenerAdapter() { 2100 @Override 2101 public void onAnimationEnd(Animator _a) { 2102 nlo.setVisibility(View.GONE); 2103 } 2104 }) 2105 .start(); 2106 } 2107 } 2108 2109 findAndUpdateMediaNotifications(); 2110 } 2111 2112 public void findAndUpdateMediaNotifications() { 2113 boolean metaDataChanged = false; 2114 2115 synchronized (mNotificationData) { 2116 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 2117 final int N = activeNotifications.size(); 2118 2119 // Promote the media notification with a controller in 'playing' state, if any. 2120 Entry mediaNotification = null; 2121 MediaController controller = null; 2122 for (int i = 0; i < N; i++) { 2123 final Entry entry = activeNotifications.get(i); 2124 if (isMediaNotification(entry)) { 2125 final MediaSession.Token token = 2126 entry.notification.getNotification().extras 2127 .getParcelable(Notification.EXTRA_MEDIA_SESSION); 2128 if (token != null) { 2129 MediaController aController = new MediaController(mContext, token); 2130 if (PlaybackState.STATE_PLAYING == 2131 getMediaControllerPlaybackState(aController)) { 2132 if (DEBUG_MEDIA) { 2133 Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching " 2134 + entry.notification.getKey()); 2135 } 2136 mediaNotification = entry; 2137 controller = aController; 2138 break; 2139 } 2140 } 2141 } 2142 } 2143 if (mediaNotification == null) { 2144 // Still nothing? OK, let's just look for live media sessions and see if they match 2145 // one of our notifications. This will catch apps that aren't (yet!) using media 2146 // notifications. 2147 2148 if (mMediaSessionManager != null) { 2149 final List<MediaController> sessions 2150 = mMediaSessionManager.getActiveSessionsForUser( 2151 null, 2152 UserHandle.USER_ALL); 2153 2154 for (MediaController aController : sessions) { 2155 if (PlaybackState.STATE_PLAYING == 2156 getMediaControllerPlaybackState(aController)) { 2157 // now to see if we have one like this 2158 final String pkg = aController.getPackageName(); 2159 2160 for (int i = 0; i < N; i++) { 2161 final Entry entry = activeNotifications.get(i); 2162 if (entry.notification.getPackageName().equals(pkg)) { 2163 if (DEBUG_MEDIA) { 2164 Log.v(TAG, "DEBUG_MEDIA: found controller matching " 2165 + entry.notification.getKey()); 2166 } 2167 controller = aController; 2168 mediaNotification = entry; 2169 break; 2170 } 2171 } 2172 } 2173 } 2174 } 2175 } 2176 2177 if (controller != null && !sameSessions(mMediaController, controller)) { 2178 // We have a new media session 2179 clearCurrentMediaNotification(); 2180 mMediaController = controller; 2181 mMediaController.registerCallback(mMediaListener); 2182 mMediaMetadata = mMediaController.getMetadata(); 2183 if (DEBUG_MEDIA) { 2184 Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " 2185 + mMediaMetadata); 2186 } 2187 2188 if (mediaNotification != null) { 2189 mMediaNotificationKey = mediaNotification.notification.getKey(); 2190 if (DEBUG_MEDIA) { 2191 Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" 2192 + mMediaNotificationKey + " controller=" + mMediaController); 2193 } 2194 } 2195 metaDataChanged = true; 2196 } 2197 } 2198 2199 if (metaDataChanged) { 2200 updateNotifications(); 2201 } 2202 updateMediaMetaData(metaDataChanged, true); 2203 } 2204 2205 private int getMediaControllerPlaybackState(MediaController controller) { 2206 if (controller != null) { 2207 final PlaybackState playbackState = controller.getPlaybackState(); 2208 if (playbackState != null) { 2209 return playbackState.getState(); 2210 } 2211 } 2212 return PlaybackState.STATE_NONE; 2213 } 2214 2215 private boolean isPlaybackActive(int state) { 2216 if (state != PlaybackState.STATE_STOPPED 2217 && state != PlaybackState.STATE_ERROR 2218 && state != PlaybackState.STATE_NONE) { 2219 return true; 2220 } 2221 return false; 2222 } 2223 2224 private void clearCurrentMediaNotification() { 2225 mMediaNotificationKey = null; 2226 mMediaMetadata = null; 2227 if (mMediaController != null) { 2228 if (DEBUG_MEDIA) { 2229 Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " 2230 + mMediaController.getPackageName()); 2231 } 2232 mMediaController.unregisterCallback(mMediaListener); 2233 } 2234 mMediaController = null; 2235 } 2236 2237 private boolean sameSessions(MediaController a, MediaController b) { 2238 if (a == b) return true; 2239 if (a == null) return false; 2240 return a.controlsSameSession(b); 2241 } 2242 2243 /** 2244 * Hide the album artwork that is fading out and release its bitmap. 2245 */ 2246 protected Runnable mHideBackdropFront = new Runnable() { 2247 @Override 2248 public void run() { 2249 if (DEBUG_MEDIA) { 2250 Log.v(TAG, "DEBUG_MEDIA: removing fade layer"); 2251 } 2252 mBackdropFront.setVisibility(View.INVISIBLE); 2253 mBackdropFront.animate().cancel(); 2254 mBackdropFront.setImageDrawable(null); 2255 } 2256 }; 2257 2258 /** 2259 * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. 2260 */ 2261 public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) { 2262 Trace.beginSection("StatusBar#updateMediaMetaData"); 2263 if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) { 2264 Trace.endSection(); 2265 return; 2266 } 2267 2268 if (mBackdrop == null) { 2269 Trace.endSection(); 2270 return; // called too early 2271 } 2272 2273 if (mLaunchTransitionFadingAway) { 2274 mBackdrop.setVisibility(View.INVISIBLE); 2275 Trace.endSection(); 2276 return; 2277 } 2278 2279 if (DEBUG_MEDIA) { 2280 Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " + mMediaNotificationKey 2281 + " metadata=" + mMediaMetadata 2282 + " metaDataChanged=" + metaDataChanged 2283 + " state=" + mState); 2284 } 2285 2286 Drawable artworkDrawable = null; 2287 if (mMediaMetadata != null) { 2288 Bitmap artworkBitmap = null; 2289 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); 2290 if (artworkBitmap == null) { 2291 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); 2292 // might still be null 2293 } 2294 if (artworkBitmap != null) { 2295 artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap); 2296 } 2297 } 2298 boolean allowWhenShade = false; 2299 if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) { 2300 Bitmap lockWallpaper = mLockscreenWallpaper.getBitmap(); 2301 if (lockWallpaper != null) { 2302 artworkDrawable = new LockscreenWallpaper.WallpaperDrawable( 2303 mBackdropBack.getResources(), lockWallpaper); 2304 // We're in the SHADE mode on the SIM screen - yet we still need to show 2305 // the lockscreen wallpaper in that mode. 2306 allowWhenShade = mStatusBarKeyguardViewManager != null 2307 && mStatusBarKeyguardViewManager.isShowing(); 2308 } 2309 } 2310 2311 boolean hideBecauseOccluded = mStatusBarKeyguardViewManager != null 2312 && mStatusBarKeyguardViewManager.isOccluded(); 2313 2314 final boolean hasArtwork = artworkDrawable != null; 2315 2316 if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) 2317 && (mState != StatusBarState.SHADE || allowWhenShade) 2318 && mFingerprintUnlockController.getMode() 2319 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING 2320 && !hideBecauseOccluded) { 2321 // time to show some art! 2322 if (mBackdrop.getVisibility() != View.VISIBLE) { 2323 mBackdrop.setVisibility(View.VISIBLE); 2324 if (allowEnterAnimation) { 2325 mBackdrop.setAlpha(SRC_MIN_ALPHA); 2326 mBackdrop.animate().alpha(1f); 2327 } else { 2328 mBackdrop.animate().cancel(); 2329 mBackdrop.setAlpha(1f); 2330 } 2331 mStatusBarWindowManager.setBackdropShowing(true); 2332 metaDataChanged = true; 2333 if (DEBUG_MEDIA) { 2334 Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork"); 2335 } 2336 } 2337 if (metaDataChanged) { 2338 if (mBackdropBack.getDrawable() != null) { 2339 Drawable drawable = 2340 mBackdropBack.getDrawable().getConstantState() 2341 .newDrawable(mBackdropFront.getResources()).mutate(); 2342 mBackdropFront.setImageDrawable(drawable); 2343 if (mScrimSrcModeEnabled) { 2344 mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode); 2345 } 2346 mBackdropFront.setAlpha(1f); 2347 mBackdropFront.setVisibility(View.VISIBLE); 2348 } else { 2349 mBackdropFront.setVisibility(View.INVISIBLE); 2350 } 2351 2352 if (DEBUG_MEDIA_FAKE_ARTWORK) { 2353 final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF); 2354 Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c)); 2355 mBackdropBack.setBackgroundColor(0xFFFFFFFF); 2356 mBackdropBack.setImageDrawable(new ColorDrawable(c)); 2357 } else { 2358 mBackdropBack.setImageDrawable(artworkDrawable); 2359 } 2360 if (mScrimSrcModeEnabled) { 2361 mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode); 2362 } 2363 2364 if (mBackdropFront.getVisibility() == View.VISIBLE) { 2365 if (DEBUG_MEDIA) { 2366 Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from " 2367 + mBackdropFront.getDrawable() 2368 + " to " 2369 + mBackdropBack.getDrawable()); 2370 } 2371 mBackdropFront.animate() 2372 .setDuration(250) 2373 .alpha(0f).withEndAction(mHideBackdropFront); 2374 } 2375 } 2376 } else { 2377 // need to hide the album art, either because we are unlocked or because 2378 // the metadata isn't there to support it 2379 if (mBackdrop.getVisibility() != View.GONE) { 2380 if (DEBUG_MEDIA) { 2381 Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork"); 2382 } 2383 if (mFingerprintUnlockController.getMode() 2384 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING 2385 || hideBecauseOccluded) { 2386 2387 // We are unlocking directly - no animation! 2388 mBackdrop.setVisibility(View.GONE); 2389 mBackdropBack.setImageDrawable(null); 2390 mStatusBarWindowManager.setBackdropShowing(false); 2391 } else { 2392 mStatusBarWindowManager.setBackdropShowing(false); 2393 mBackdrop.animate() 2394 .alpha(SRC_MIN_ALPHA) 2395 .setInterpolator(Interpolators.ACCELERATE_DECELERATE) 2396 .setDuration(300) 2397 .setStartDelay(0) 2398 .withEndAction(new Runnable() { 2399 @Override 2400 public void run() { 2401 mBackdrop.setVisibility(View.GONE); 2402 mBackdropFront.animate().cancel(); 2403 mBackdropBack.setImageDrawable(null); 2404 mHandler.post(mHideBackdropFront); 2405 } 2406 }); 2407 if (mKeyguardFadingAway) { 2408 mBackdrop.animate() 2409 // Make it disappear faster, as the focus should be on the activity 2410 // behind. 2411 .setDuration(mKeyguardFadingAwayDuration / 2) 2412 .setStartDelay(mKeyguardFadingAwayDelay) 2413 .setInterpolator(Interpolators.LINEAR) 2414 .start(); 2415 } 2416 } 2417 } 2418 } 2419 Trace.endSection(); 2420 } 2421 2422 private void updateReportRejectedTouchVisibility() { 2423 if (mReportRejectedTouch == null) { 2424 return; 2425 } 2426 mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD 2427 && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE); 2428 } 2429 2430 /** 2431 * State is one or more of the DISABLE constants from StatusBarManager. 2432 */ 2433 @Override 2434 public void disable(int state1, int state2, boolean animate) { 2435 animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN; 2436 mDisabledUnmodified1 = state1; 2437 mDisabledUnmodified2 = state2; 2438 final int old1 = mDisabled1; 2439 final int diff1 = state1 ^ old1; 2440 mDisabled1 = state1; 2441 2442 final int old2 = mDisabled2; 2443 final int diff2 = state2 ^ old2; 2444 mDisabled2 = state2; 2445 2446 if (DEBUG) { 2447 Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", 2448 old1, state1, diff1)); 2449 Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", 2450 old2, state2, diff2)); 2451 } 2452 2453 StringBuilder flagdbg = new StringBuilder(); 2454 flagdbg.append("disable: < "); 2455 flagdbg.append(((state1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "EXPAND" : "expand"); 2456 flagdbg.append(((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "* " : " "); 2457 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "ICONS" : "icons"); 2458 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " "); 2459 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts"); 2460 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " "); 2461 flagdbg.append(((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info"); 2462 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " "); 2463 flagdbg.append(((state1 & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back"); 2464 flagdbg.append(((diff1 & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " "); 2465 flagdbg.append(((state1 & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home"); 2466 flagdbg.append(((diff1 & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " "); 2467 flagdbg.append(((state1 & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent"); 2468 flagdbg.append(((diff1 & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " "); 2469 flagdbg.append(((state1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock"); 2470 flagdbg.append(((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " "); 2471 flagdbg.append(((state1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search"); 2472 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " "); 2473 flagdbg.append(((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "QUICK_SETTINGS" 2474 : "quick_settings"); 2475 flagdbg.append(((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "* " : " "); 2476 flagdbg.append(">"); 2477 Log.d(TAG, flagdbg.toString()); 2478 2479 if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { 2480 if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { 2481 animateCollapsePanels(); 2482 } 2483 } 2484 2485 if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) { 2486 if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) { 2487 // close recents if it's visible 2488 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 2489 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 2490 } 2491 } 2492 2493 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { 2494 mDisableNotificationAlerts = 2495 (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0; 2496 mHeadsUpObserver.onChange(true); 2497 } 2498 2499 if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) { 2500 updateQsExpansionEnabled(); 2501 } 2502 } 2503 2504 /** 2505 * Reapplies the disable flags as last requested by StatusBarManager. 2506 * 2507 * This needs to be called if state used by {@link #adjustDisableFlags} changes. 2508 */ 2509 public void recomputeDisableFlags(boolean animate) { 2510 mCommandQueue.recomputeDisableFlags(animate); 2511 } 2512 2513 protected H createHandler() { 2514 return new StatusBar.H(); 2515 } 2516 2517 @Override 2518 public void startActivity(Intent intent, boolean dismissShade) { 2519 startActivityDismissingKeyguard(intent, false, dismissShade); 2520 } 2521 2522 @Override 2523 public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { 2524 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade); 2525 } 2526 2527 @Override 2528 public void startActivity(Intent intent, boolean dismissShade, Callback callback) { 2529 startActivityDismissingKeyguard(intent, false, dismissShade, callback); 2530 } 2531 2532 public void setQsExpanded(boolean expanded) { 2533 mStatusBarWindowManager.setQsExpanded(expanded); 2534 mKeyguardStatusView.setImportantForAccessibility(expanded 2535 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 2536 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); 2537 } 2538 2539 public boolean isGoingToNotificationShade() { 2540 return mLeaveOpenOnKeyguardHide; 2541 } 2542 2543 public boolean isWakeUpComingFromTouch() { 2544 return mWakeUpComingFromTouch; 2545 } 2546 2547 public boolean isFalsingThresholdNeeded() { 2548 return getBarState() == StatusBarState.KEYGUARD; 2549 } 2550 2551 public boolean isDozing() { 2552 return mDozing; 2553 } 2554 2555 @Override // NotificationData.Environment 2556 public String getCurrentMediaNotificationKey() { 2557 return mMediaNotificationKey; 2558 } 2559 2560 public boolean isScrimSrcModeEnabled() { 2561 return mScrimSrcModeEnabled; 2562 } 2563 2564 /** 2565 * To be called when there's a state change in StatusBarKeyguardViewManager. 2566 */ 2567 public void onKeyguardViewManagerStatesUpdated() { 2568 logStateToEventlog(); 2569 } 2570 2571 @Override // UnlockMethodCache.OnUnlockMethodChangedListener 2572 public void onUnlockMethodStateChanged() { 2573 logStateToEventlog(); 2574 } 2575 2576 @Override 2577 public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { 2578 if (inPinnedMode) { 2579 mStatusBarWindowManager.setHeadsUpShowing(true); 2580 mStatusBarWindowManager.setForceStatusBarVisible(true); 2581 if (mNotificationPanel.isFullyCollapsed()) { 2582 // We need to ensure that the touchable region is updated before the window will be 2583 // resized, in order to not catch any touches. A layout will ensure that 2584 // onComputeInternalInsets will be called and after that we can resize the layout. Let's 2585 // make sure that the window stays small for one frame until the touchableRegion is set. 2586 mNotificationPanel.requestLayout(); 2587 mStatusBarWindowManager.setForceWindowCollapsed(true); 2588 mNotificationPanel.post(new Runnable() { 2589 @Override 2590 public void run() { 2591 mStatusBarWindowManager.setForceWindowCollapsed(false); 2592 } 2593 }); 2594 } 2595 } else { 2596 if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) { 2597 // We are currently tracking or is open and the shade doesn't need to be kept 2598 // open artificially. 2599 mStatusBarWindowManager.setHeadsUpShowing(false); 2600 } else { 2601 // we need to keep the panel open artificially, let's wait until the animation 2602 // is finished. 2603 mHeadsUpManager.setHeadsUpGoingAway(true); 2604 mStackScroller.runAfterAnimationFinished(new Runnable() { 2605 @Override 2606 public void run() { 2607 if (!mHeadsUpManager.hasPinnedHeadsUp()) { 2608 mStatusBarWindowManager.setHeadsUpShowing(false); 2609 mHeadsUpManager.setHeadsUpGoingAway(false); 2610 } 2611 removeRemoteInputEntriesKeptUntilCollapsed(); 2612 } 2613 }); 2614 } 2615 } 2616 } 2617 2618 @Override 2619 public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { 2620 dismissVolumeDialog(); 2621 } 2622 2623 @Override 2624 public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { 2625 } 2626 2627 @Override 2628 public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { 2629 if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) { 2630 removeNotification(entry.key, mLatestRankingMap); 2631 mHeadsUpEntriesToRemoveOnSwitch.remove(entry); 2632 if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) { 2633 mLatestRankingMap = null; 2634 } 2635 } else { 2636 updateNotificationRanking(null); 2637 if (isHeadsUp) { 2638 mDozeServiceHost.fireNotificationHeadsUp(); 2639 } 2640 } 2641 2642 } 2643 2644 protected void updateHeadsUp(String key, Entry entry, boolean shouldPeek, 2645 boolean alertAgain) { 2646 final boolean wasHeadsUp = isHeadsUp(key); 2647 if (wasHeadsUp) { 2648 if (!shouldPeek) { 2649 // We don't want this to be interrupting anymore, lets remove it 2650 mHeadsUpManager.removeNotification(key, false /* ignoreEarliestRemovalTime */); 2651 } else { 2652 mHeadsUpManager.updateNotification(entry, alertAgain); 2653 } 2654 } else if (shouldPeek && alertAgain) { 2655 // This notification was updated to be a heads-up, show it! 2656 mHeadsUpManager.showNotification(entry); 2657 } 2658 } 2659 2660 protected void setHeadsUpUser(int newUserId) { 2661 if (mHeadsUpManager != null) { 2662 mHeadsUpManager.setUser(newUserId); 2663 } 2664 } 2665 2666 public boolean isHeadsUp(String key) { 2667 return mHeadsUpManager.isHeadsUp(key); 2668 } 2669 2670 protected boolean isSnoozedPackage(StatusBarNotification sbn) { 2671 return mHeadsUpManager.isSnoozed(sbn.getPackageName()); 2672 } 2673 2674 public boolean isKeyguardCurrentlySecure() { 2675 return !mUnlockMethodCache.canSkipBouncer(); 2676 } 2677 2678 public void setPanelExpanded(boolean isExpanded) { 2679 mPanelExpanded = isExpanded; 2680 mStatusBarWindowManager.setPanelExpanded(isExpanded); 2681 mVisualStabilityManager.setPanelExpanded(isExpanded); 2682 if (isExpanded && getBarState() != StatusBarState.KEYGUARD) { 2683 if (DEBUG) { 2684 Log.v(TAG, "clearing notification effects from setPanelExpanded"); 2685 } 2686 clearNotificationEffects(); 2687 } 2688 2689 if (!isExpanded) { 2690 removeRemoteInputEntriesKeptUntilCollapsed(); 2691 } 2692 } 2693 2694 private void removeRemoteInputEntriesKeptUntilCollapsed() { 2695 for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) { 2696 Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i); 2697 mRemoteInputController.removeRemoteInput(entry, null); 2698 removeNotification(entry.key, mLatestRankingMap); 2699 } 2700 mRemoteInputEntriesToRemoveOnCollapse.clear(); 2701 } 2702 2703 public void onScreenTurnedOff() { 2704 mFalsingManager.onScreenOff(); 2705 } 2706 2707 public NotificationStackScrollLayout getNotificationScrollLayout() { 2708 return mStackScroller; 2709 } 2710 2711 public boolean isPulsing() { 2712 return mDozeScrimController.isPulsing(); 2713 } 2714 2715 @Override 2716 public void onReorderingAllowed() { 2717 updateNotifications(); 2718 } 2719 2720 public boolean isLaunchTransitionFadingAway() { 2721 return mLaunchTransitionFadingAway; 2722 } 2723 2724 public boolean hideStatusBarIconsWhenExpanded() { 2725 return mNotificationPanel.hideStatusBarIconsWhenExpanded(); 2726 } 2727 2728 /** 2729 * All changes to the status bar and notifications funnel through here and are batched. 2730 */ 2731 protected class H extends Handler { 2732 @Override 2733 public void handleMessage(Message m) { 2734 switch (m.what) { 2735 case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU: 2736 toggleKeyboardShortcuts(m.arg1); 2737 break; 2738 case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU: 2739 dismissKeyboardShortcuts(); 2740 break; 2741 // End old BaseStatusBar.H handling. 2742 case MSG_OPEN_NOTIFICATION_PANEL: 2743 animateExpandNotificationsPanel(); 2744 break; 2745 case MSG_OPEN_SETTINGS_PANEL: 2746 animateExpandSettingsPanel((String) m.obj); 2747 break; 2748 case MSG_CLOSE_PANELS: 2749 animateCollapsePanels(); 2750 break; 2751 case MSG_LAUNCH_TRANSITION_TIMEOUT: 2752 onLaunchTransitionTimeout(); 2753 break; 2754 } 2755 } 2756 } 2757 2758 public void maybeEscalateHeadsUp() { 2759 Collection<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getAllEntries(); 2760 for (HeadsUpManager.HeadsUpEntry entry : entries) { 2761 final StatusBarNotification sbn = entry.entry.notification; 2762 final Notification notification = sbn.getNotification(); 2763 if (notification.fullScreenIntent != null) { 2764 if (DEBUG) { 2765 Log.d(TAG, "converting a heads up to fullScreen"); 2766 } 2767 try { 2768 EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, 2769 sbn.getKey()); 2770 notification.fullScreenIntent.send(); 2771 entry.entry.notifyFullScreenIntentLaunched(); 2772 } catch (PendingIntent.CanceledException e) { 2773 } 2774 } 2775 } 2776 mHeadsUpManager.releaseAllImmediately(); 2777 } 2778 2779 /** 2780 * Called for system navigation gestures. First action opens the panel, second opens 2781 * settings. Down action closes the entire panel. 2782 */ 2783 @Override 2784 public void handleSystemNavigationKey(int key) { 2785 if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key); 2786 if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive() 2787 || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) { 2788 return; 2789 } 2790 2791 // Panels are not available in setup 2792 if (!mUserSetup) return; 2793 2794 if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) { 2795 MetricsLogger.action(mContext, MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP); 2796 mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */); 2797 } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) { 2798 MetricsLogger.action(mContext, MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN); 2799 if (mNotificationPanel.isFullyCollapsed()) { 2800 mNotificationPanel.expand(true /* animate */); 2801 MetricsLogger.count(mContext, NotificationPanelView.COUNTER_PANEL_OPEN, 1); 2802 } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){ 2803 mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */); 2804 MetricsLogger.count(mContext, NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1); 2805 } 2806 } 2807 2808 } 2809 2810 boolean panelsEnabled() { 2811 return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS; 2812 } 2813 2814 void makeExpandedVisible(boolean force) { 2815 if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); 2816 if (!force && (mExpandedVisible || !panelsEnabled())) { 2817 return; 2818 } 2819 2820 mExpandedVisible = true; 2821 2822 // Expand the window to encompass the full screen in anticipation of the drag. 2823 // This is only possible to do atomically because the status bar is at the top of the screen! 2824 mStatusBarWindowManager.setPanelVisible(true); 2825 2826 visibilityChanged(true); 2827 mWaitingForKeyguardExit = false; 2828 recomputeDisableFlags(!force /* animate */); 2829 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 2830 } 2831 2832 public void animateCollapsePanels() { 2833 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); 2834 } 2835 2836 private final Runnable mAnimateCollapsePanels = new Runnable() { 2837 @Override 2838 public void run() { 2839 animateCollapsePanels(); 2840 } 2841 }; 2842 2843 public void postAnimateCollapsePanels() { 2844 mHandler.post(mAnimateCollapsePanels); 2845 } 2846 2847 public void postAnimateOpenPanels() { 2848 mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL); 2849 } 2850 2851 @Override 2852 public void animateCollapsePanels(int flags) { 2853 animateCollapsePanels(flags, false /* force */, false /* delayed */, 2854 1.0f /* speedUpFactor */); 2855 } 2856 2857 public void animateCollapsePanels(int flags, boolean force) { 2858 animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */); 2859 } 2860 2861 public void animateCollapsePanels(int flags, boolean force, boolean delayed) { 2862 animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */); 2863 } 2864 2865 public void animateCollapsePanels(int flags, boolean force, boolean delayed, 2866 float speedUpFactor) { 2867 if (!force && mState != StatusBarState.SHADE) { 2868 runPostCollapseRunnables(); 2869 return; 2870 } 2871 if (SPEW) { 2872 Log.d(TAG, "animateCollapse():" 2873 + " mExpandedVisible=" + mExpandedVisible 2874 + " flags=" + flags); 2875 } 2876 2877 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) { 2878 if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) { 2879 mHandler.removeMessages(MSG_HIDE_RECENT_APPS); 2880 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); 2881 } 2882 } 2883 2884 if (mStatusBarWindow != null && mNotificationPanel.canPanelBeCollapsed()) { 2885 // release focus immediately to kick off focus change transition 2886 mStatusBarWindowManager.setStatusBarFocusable(false); 2887 2888 mStatusBarWindow.cancelExpandHelper(); 2889 mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor); 2890 } 2891 } 2892 2893 private void runPostCollapseRunnables() { 2894 ArrayList<Runnable> clonedList = new ArrayList<>(mPostCollapseRunnables); 2895 mPostCollapseRunnables.clear(); 2896 int size = clonedList.size(); 2897 for (int i = 0; i < size; i++) { 2898 clonedList.get(i).run(); 2899 } 2900 mStatusBarKeyguardViewManager.readyForKeyguardDone(); 2901 } 2902 2903 @Override 2904 public void animateExpandNotificationsPanel() { 2905 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2906 if (!panelsEnabled()) { 2907 return ; 2908 } 2909 2910 mNotificationPanel.expand(true /* animate */); 2911 2912 if (false) postStartTracing(); 2913 } 2914 2915 @Override 2916 public void animateExpandSettingsPanel(String subPanel) { 2917 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); 2918 if (!panelsEnabled()) { 2919 return; 2920 } 2921 2922 // Settings are not available in setup 2923 if (!mUserSetup) return; 2924 2925 2926 if (subPanel != null) { 2927 mQSPanel.openDetails(subPanel); 2928 } 2929 mNotificationPanel.expandWithQs(); 2930 2931 if (false) postStartTracing(); 2932 } 2933 2934 public void animateCollapseQuickSettings() { 2935 if (mState == StatusBarState.SHADE) { 2936 mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */); 2937 } 2938 } 2939 2940 void makeExpandedInvisible() { 2941 if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible 2942 + " mExpandedVisible=" + mExpandedVisible); 2943 2944 if (!mExpandedVisible || mStatusBarWindow == null) { 2945 return; 2946 } 2947 2948 // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) 2949 mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/, 2950 1.0f /* speedUpFactor */); 2951 2952 mNotificationPanel.closeQs(); 2953 2954 mExpandedVisible = false; 2955 visibilityChanged(false); 2956 2957 // Shrink the window to the size of the status bar only 2958 mStatusBarWindowManager.setPanelVisible(false); 2959 mStatusBarWindowManager.setForceStatusBarVisible(false); 2960 2961 // Close any "App info" popups that might have snuck on-screen 2962 dismissPopups(); 2963 2964 runPostCollapseRunnables(); 2965 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 2966 showBouncerIfKeyguard(); 2967 recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */); 2968 2969 // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in 2970 // the bouncer appear animation. 2971 if (!mStatusBarKeyguardViewManager.isShowing()) { 2972 WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 2973 } 2974 } 2975 2976 public boolean interceptTouchEvent(MotionEvent event) { 2977 if (DEBUG_GESTURES) { 2978 if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { 2979 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, 2980 event.getActionMasked(), (int) event.getX(), (int) event.getY(), 2981 mDisabled1, mDisabled2); 2982 } 2983 2984 } 2985 2986 if (SPEW) { 2987 Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" 2988 + mDisabled1 + " mDisabled2=" + mDisabled2 + " mTracking=" + mTracking); 2989 } else if (CHATTY) { 2990 if (event.getAction() != MotionEvent.ACTION_MOVE) { 2991 Log.d(TAG, String.format( 2992 "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", 2993 MotionEvent.actionToString(event.getAction()), 2994 event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); 2995 } 2996 } 2997 2998 if (DEBUG_GESTURES) { 2999 mGestureRec.add(event); 3000 } 3001 3002 if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { 3003 final boolean upOrCancel = 3004 event.getAction() == MotionEvent.ACTION_UP || 3005 event.getAction() == MotionEvent.ACTION_CANCEL; 3006 if (upOrCancel && !mExpandedVisible) { 3007 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); 3008 } else { 3009 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); 3010 } 3011 } 3012 return false; 3013 } 3014 3015 public GestureRecorder getGestureRecorder() { 3016 return mGestureRec; 3017 } 3018 3019 public FingerprintUnlockController getFingerprintUnlockController() { 3020 return mFingerprintUnlockController; 3021 } 3022 3023 @Override // CommandQueue 3024 public void setWindowState(int window, int state) { 3025 boolean showing = state == WINDOW_STATE_SHOWING; 3026 if (mStatusBarWindow != null 3027 && window == StatusBarManager.WINDOW_STATUS_BAR 3028 && mStatusBarWindowState != state) { 3029 mStatusBarWindowState = state; 3030 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); 3031 if (!showing && mState == StatusBarState.SHADE) { 3032 mStatusBarView.collapsePanel(false /* animate */, false /* delayed */, 3033 1.0f /* speedUpFactor */); 3034 } 3035 } 3036 } 3037 3038 @Override // CommandQueue 3039 public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, 3040 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { 3041 final int oldVal = mSystemUiVisibility; 3042 final int newVal = (oldVal&~mask) | (vis&mask); 3043 final int diff = newVal ^ oldVal; 3044 if (DEBUG) Log.d(TAG, String.format( 3045 "setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s", 3046 Integer.toHexString(vis), Integer.toHexString(mask), 3047 Integer.toHexString(oldVal), Integer.toHexString(newVal), 3048 Integer.toHexString(diff))); 3049 boolean sbModeChanged = false; 3050 if (diff != 0) { 3051 mSystemUiVisibility = newVal; 3052 3053 // update low profile 3054 if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) { 3055 setAreThereNotifications(); 3056 } 3057 3058 // ready to unhide 3059 if ((vis & View.STATUS_BAR_UNHIDE) != 0) { 3060 mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE; 3061 mNoAnimationOnNextBarModeChange = true; 3062 } 3063 3064 // update status bar mode 3065 final int sbMode = computeStatusBarMode(oldVal, newVal); 3066 3067 sbModeChanged = sbMode != -1; 3068 if (sbModeChanged && sbMode != mStatusBarMode) { 3069 if (sbMode != mStatusBarMode) { 3070 mStatusBarMode = sbMode; 3071 checkBarModes(); 3072 } 3073 touchAutoHide(); 3074 } 3075 3076 if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) { 3077 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE; 3078 } 3079 3080 // send updated sysui visibility to window manager 3081 notifyUiVisibilityChanged(mSystemUiVisibility); 3082 } 3083 3084 mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis, 3085 mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode); 3086 } 3087 3088 void touchAutoHide() { 3089 // update transient bar autohide 3090 if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null 3091 && mNavigationBar.isSemiTransparent())) { 3092 scheduleAutohide(); 3093 } else { 3094 cancelAutohide(); 3095 } 3096 } 3097 3098 protected int computeStatusBarMode(int oldVal, int newVal) { 3099 return computeBarMode(oldVal, newVal, View.STATUS_BAR_TRANSIENT, 3100 View.STATUS_BAR_TRANSLUCENT, View.STATUS_BAR_TRANSPARENT); 3101 } 3102 3103 protected BarTransitions getStatusBarTransitions() { 3104 return mStatusBarView.getBarTransitions(); 3105 } 3106 3107 protected int computeBarMode(int oldVis, int newVis, 3108 int transientFlag, int translucentFlag, int transparentFlag) { 3109 final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag); 3110 final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag); 3111 if (oldMode == newMode) { 3112 return -1; // no mode change 3113 } 3114 return newMode; 3115 } 3116 3117 private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) { 3118 int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag; 3119 return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT 3120 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT 3121 : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT 3122 : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT 3123 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT 3124 : MODE_OPAQUE; 3125 } 3126 3127 void checkBarModes() { 3128 if (mDemoMode) return; 3129 if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState, 3130 getStatusBarTransitions()); 3131 if (mNavigationBar != null) mNavigationBar.checkNavBarModes(); 3132 mNoAnimationOnNextBarModeChange = false; 3133 } 3134 3135 // Called by NavigationBarFragment 3136 void setQsScrimEnabled(boolean scrimEnabled) { 3137 mNotificationPanel.setQsScrimEnabled(scrimEnabled); 3138 } 3139 3140 void checkBarMode(int mode, int windowState, BarTransitions transitions) { 3141 final boolean powerSave = mBatteryController.isPowerSave(); 3142 final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive 3143 && windowState != WINDOW_STATE_HIDDEN && !powerSave; 3144 if (powerSave && getBarState() == StatusBarState.SHADE) { 3145 mode = MODE_WARNING; 3146 } 3147 transitions.transitionTo(mode, anim); 3148 } 3149 3150 private void finishBarAnimations() { 3151 if (mStatusBarView != null) { 3152 mStatusBarView.getBarTransitions().finishAnimations(); 3153 } 3154 if (mNavigationBar != null) { 3155 mNavigationBar.finishBarAnimations(); 3156 } 3157 } 3158 3159 private final Runnable mCheckBarModes = new Runnable() { 3160 @Override 3161 public void run() { 3162 checkBarModes(); 3163 } 3164 }; 3165 3166 public void setInteracting(int barWindow, boolean interacting) { 3167 final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting; 3168 mInteractingWindows = interacting 3169 ? (mInteractingWindows | barWindow) 3170 : (mInteractingWindows & ~barWindow); 3171 if (mInteractingWindows != 0) { 3172 suspendAutohide(); 3173 } else { 3174 resumeSuspendedAutohide(); 3175 } 3176 // manually dismiss the volume panel when interacting with the nav bar 3177 if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) { 3178 dismissVolumeDialog(); 3179 } 3180 checkBarModes(); 3181 } 3182 3183 private void dismissVolumeDialog() { 3184 if (mVolumeComponent != null) { 3185 mVolumeComponent.dismissNow(); 3186 } 3187 } 3188 3189 private void resumeSuspendedAutohide() { 3190 if (mAutohideSuspended) { 3191 scheduleAutohide(); 3192 mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher 3193 } 3194 } 3195 3196 private void suspendAutohide() { 3197 mHandler.removeCallbacks(mAutohide); 3198 mHandler.removeCallbacks(mCheckBarModes); 3199 mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0; 3200 } 3201 3202 private void cancelAutohide() { 3203 mAutohideSuspended = false; 3204 mHandler.removeCallbacks(mAutohide); 3205 } 3206 3207 private void scheduleAutohide() { 3208 cancelAutohide(); 3209 mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); 3210 } 3211 3212 void checkUserAutohide(View v, MotionEvent event) { 3213 if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed 3214 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar 3215 && event.getX() == 0 && event.getY() == 0 // a touch outside both bars 3216 && !mRemoteInputController.isRemoteInputActive()) { // not due to typing in IME 3217 userAutohide(); 3218 } 3219 } 3220 3221 private void checkRemoteInputOutside(MotionEvent event) { 3222 if (event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar 3223 && event.getX() == 0 && event.getY() == 0 // a touch outside both bars 3224 && mRemoteInputController.isRemoteInputActive()) { 3225 mRemoteInputController.closeRemoteInputs(); 3226 } 3227 } 3228 3229 private void userAutohide() { 3230 cancelAutohide(); 3231 mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear 3232 } 3233 3234 private boolean areLightsOn() { 3235 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); 3236 } 3237 3238 public void setLightsOn(boolean on) { 3239 Log.v(TAG, "setLightsOn(" + on + ")"); 3240 if (on) { 3241 setSystemUiVisibility(0, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE, 3242 mLastFullscreenStackBounds, mLastDockedStackBounds); 3243 } else { 3244 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, 0, 0, 3245 View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds, 3246 mLastDockedStackBounds); 3247 } 3248 } 3249 3250 private void notifyUiVisibilityChanged(int vis) { 3251 try { 3252 if (mLastDispatchedSystemUiVisibility != vis) { 3253 mWindowManagerService.statusBarVisibilityChanged(vis); 3254 mLastDispatchedSystemUiVisibility = vis; 3255 } 3256 } catch (RemoteException ex) { 3257 } 3258 } 3259 3260 @Override 3261 public void topAppWindowChanged(boolean showMenu) { 3262 if (SPEW) { 3263 Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button"); 3264 } 3265 3266 // See above re: lights-out policy for legacy apps. 3267 if (showMenu) setLightsOn(true); 3268 } 3269 3270 public static String viewInfo(View v) { 3271 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() 3272 + ") " + v.getWidth() + "x" + v.getHeight() + "]"; 3273 } 3274 3275 @Override 3276 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3277 synchronized (mQueueLock) { 3278 pw.println("Current Status Bar state:"); 3279 pw.println(" mExpandedVisible=" + mExpandedVisible 3280 + ", mTrackingPosition=" + mTrackingPosition); 3281 pw.println(" mTracking=" + mTracking); 3282 pw.println(" mDisplayMetrics=" + mDisplayMetrics); 3283 pw.println(" mStackScroller: " + viewInfo(mStackScroller)); 3284 pw.println(" mStackScroller: " + viewInfo(mStackScroller) 3285 + " scroll " + mStackScroller.getScrollX() 3286 + "," + mStackScroller.getScrollY()); 3287 } 3288 3289 pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); 3290 pw.print(" mStatusBarWindowState="); 3291 pw.println(windowStateToString(mStatusBarWindowState)); 3292 pw.print(" mStatusBarMode="); 3293 pw.println(BarTransitions.modeToString(mStatusBarMode)); 3294 pw.print(" mDozing="); pw.println(mDozing); 3295 pw.print(" mZenMode="); 3296 pw.println(Settings.Global.zenModeToString(mZenMode)); 3297 pw.print(" mUseHeadsUp="); 3298 pw.println(mUseHeadsUp); 3299 dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); 3300 3301 pw.print(" mMediaSessionManager="); 3302 pw.println(mMediaSessionManager); 3303 pw.print(" mMediaNotificationKey="); 3304 pw.println(mMediaNotificationKey); 3305 pw.print(" mMediaController="); 3306 pw.print(mMediaController); 3307 if (mMediaController != null) { 3308 pw.print(" state=" + mMediaController.getPlaybackState()); 3309 } 3310 pw.println(); 3311 pw.print(" mMediaMetadata="); 3312 pw.print(mMediaMetadata); 3313 if (mMediaMetadata != null) { 3314 pw.print(" title=" + mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE)); 3315 } 3316 pw.println(); 3317 3318 pw.println(" Panels: "); 3319 if (mNotificationPanel != null) { 3320 pw.println(" mNotificationPanel=" + 3321 mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug("")); 3322 pw.print (" "); 3323 mNotificationPanel.dump(fd, pw, args); 3324 } 3325 3326 DozeLog.dump(pw); 3327 3328 if (DUMPTRUCK) { 3329 synchronized (mNotificationData) { 3330 mNotificationData.dump(pw, " "); 3331 } 3332 3333 if (false) { 3334 pw.println("see the logcat for a dump of the views we have created."); 3335 // must happen on ui thread 3336 mHandler.post(new Runnable() { 3337 @Override 3338 public void run() { 3339 mStatusBarView.getLocationOnScreen(mAbsPos); 3340 Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] 3341 + ") " + mStatusBarView.getWidth() + "x" 3342 + getStatusBarHeight()); 3343 mStatusBarView.debug(); 3344 } 3345 }); 3346 } 3347 } 3348 3349 if (DEBUG_GESTURES) { 3350 pw.print(" status bar gestures: "); 3351 mGestureRec.dump(fd, pw, args); 3352 } 3353 3354 if (mHeadsUpManager != null) { 3355 mHeadsUpManager.dump(fd, pw, args); 3356 } else { 3357 pw.println(" mHeadsUpManager: null"); 3358 } 3359 if (mGroupManager != null) { 3360 mGroupManager.dump(fd, pw, args); 3361 } else { 3362 pw.println(" mGroupManager: null"); 3363 } 3364 3365 mLightBarController.dump(fd, pw, args); 3366 3367 if (KeyguardUpdateMonitor.getInstance(mContext) != null) { 3368 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args); 3369 } 3370 3371 FalsingManager.getInstance(mContext).dump(pw); 3372 FalsingLog.dump(pw); 3373 3374 pw.println("SharedPreferences:"); 3375 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) { 3376 pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); 3377 } 3378 } 3379 3380 static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) { 3381 pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode="); 3382 pw.println(BarTransitions.modeToString(transitions.getMode())); 3383 } 3384 3385 public void createAndAddWindows() { 3386 addStatusBarWindow(); 3387 } 3388 3389 private void addStatusBarWindow() { 3390 makeStatusBarView(); 3391 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class); 3392 mRemoteInputController = new RemoteInputController(mHeadsUpManager); 3393 mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); 3394 } 3395 3396 // called by makeStatusbar and also by PhoneStatusBarView 3397 void updateDisplaySize() { 3398 mDisplay.getMetrics(mDisplayMetrics); 3399 mDisplay.getSize(mCurrentDisplaySize); 3400 if (DEBUG_GESTURES) { 3401 mGestureRec.tag("display", 3402 String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); 3403 } 3404 } 3405 3406 float getDisplayDensity() { 3407 return mDisplayMetrics.density; 3408 } 3409 3410 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 3411 boolean dismissShade) { 3412 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */); 3413 } 3414 3415 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, 3416 final boolean dismissShade, final Callback callback) { 3417 if (onlyProvisioned && !isDeviceProvisioned()) return; 3418 3419 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( 3420 mContext, intent, mCurrentUserId); 3421 Runnable runnable = new Runnable() { 3422 @Override 3423 public void run() { 3424 mAssistManager.hideAssist(); 3425 intent.setFlags( 3426 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 3427 int result = ActivityManager.START_CANCELED; 3428 ActivityOptions options = new ActivityOptions(getActivityOptions()); 3429 if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) { 3430 // Normally an activity will set it's requested rotation 3431 // animation on its window. However when launching an activity 3432 // causes the orientation to change this is too late. In these cases 3433 // the default animation is used. This doesn't look good for 3434 // the camera (as it rotates the camera contents out of sync 3435 // with physical reality). So, we ask the WindowManager to 3436 // force the crossfade animation if an orientation change 3437 // happens to occur during the launch. 3438 options.setRotationAnimationHint( 3439 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); 3440 } 3441 try { 3442 result = ActivityManager.getService().startActivityAsUser( 3443 null, mContext.getBasePackageName(), 3444 intent, 3445 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 3446 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, 3447 options.toBundle(), UserHandle.CURRENT.getIdentifier()); 3448 } catch (RemoteException e) { 3449 Log.w(TAG, "Unable to start activity", e); 3450 } 3451 if (callback != null) { 3452 callback.onActivityStarted(result); 3453 } 3454 } 3455 }; 3456 Runnable cancelRunnable = new Runnable() { 3457 @Override 3458 public void run() { 3459 if (callback != null) { 3460 callback.onActivityStarted(ActivityManager.START_CANCELED); 3461 } 3462 } 3463 }; 3464 executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, 3465 afterKeyguardGone, true /* deferred */); 3466 } 3467 3468 public void readyForKeyguardDone() { 3469 mStatusBarKeyguardViewManager.readyForKeyguardDone(); 3470 } 3471 3472 public void executeRunnableDismissingKeyguard(final Runnable runnable, 3473 final Runnable cancelAction, 3474 final boolean dismissShade, 3475 final boolean afterKeyguardGone, 3476 final boolean deferred) { 3477 dismissKeyguardThenExecute(() -> { 3478 if (runnable != null) { 3479 if (mStatusBarKeyguardViewManager.isShowing() 3480 && mStatusBarKeyguardViewManager.isOccluded()) { 3481 mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); 3482 } else { 3483 AsyncTask.execute(runnable); 3484 } 3485 } 3486 if (dismissShade) { 3487 if (mExpandedVisible) { 3488 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, 3489 true /* delayed*/); 3490 } else { 3491 3492 // Do it after DismissAction has been processed to conserve the needed ordering. 3493 mHandler.post(this::runPostCollapseRunnables); 3494 } 3495 } 3496 return deferred; 3497 }, cancelAction, afterKeyguardGone); 3498 } 3499 3500 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 3501 @Override 3502 public void onReceive(Context context, Intent intent) { 3503 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 3504 String action = intent.getAction(); 3505 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { 3506 KeyboardShortcuts.dismiss(); 3507 if (mRemoteInputController != null) { 3508 mRemoteInputController.closeRemoteInputs(); 3509 } 3510 if (isCurrentProfile(getSendingUserId())) { 3511 int flags = CommandQueue.FLAG_EXCLUDE_NONE; 3512 String reason = intent.getStringExtra("reason"); 3513 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { 3514 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; 3515 } 3516 animateCollapsePanels(flags); 3517 } 3518 } 3519 else if (Intent.ACTION_SCREEN_OFF.equals(action)) { 3520 notifyHeadsUpScreenOff(); 3521 finishBarAnimations(); 3522 resetUserExpandedStates(); 3523 } 3524 else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) { 3525 mQSPanel.showDeviceMonitoringDialog(); 3526 } 3527 } 3528 }; 3529 3530 private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { 3531 @Override 3532 public void onReceive(Context context, Intent intent) { 3533 if (DEBUG) Log.v(TAG, "onReceive: " + intent); 3534 String action = intent.getAction(); 3535 if (ACTION_DEMO.equals(action)) { 3536 Bundle bundle = intent.getExtras(); 3537 if (bundle != null) { 3538 String command = bundle.getString("command", "").trim().toLowerCase(); 3539 if (command.length() > 0) { 3540 try { 3541 dispatchDemoCommand(command, bundle); 3542 } catch (Throwable t) { 3543 Log.w(TAG, "Error running demo command, intent=" + intent, t); 3544 } 3545 } 3546 } 3547 } else if (ACTION_FAKE_ARTWORK.equals(action)) { 3548 if (DEBUG_MEDIA_FAKE_ARTWORK) { 3549 updateMediaMetaData(true, true); 3550 } 3551 } 3552 } 3553 }; 3554 3555 public void resetUserExpandedStates() { 3556 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); 3557 final int notificationCount = activeNotifications.size(); 3558 for (int i = 0; i < notificationCount; i++) { 3559 NotificationData.Entry entry = activeNotifications.get(i); 3560 if (entry.row != null) { 3561 entry.row.resetUserExpansion(); 3562 } 3563 } 3564 } 3565 3566 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { 3567 dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); 3568 } 3569 3570 private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, 3571 boolean afterKeyguardGone) { 3572 if (mStatusBarKeyguardViewManager.isShowing()) { 3573 mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, 3574 afterKeyguardGone); 3575 } else { 3576 action.onDismiss(); 3577 } 3578 } 3579 3580 // SystemUIService notifies SystemBars of configuration changes, which then calls down here 3581 @Override 3582 protected void onConfigurationChanged(Configuration newConfig) { 3583 updateResources(); 3584 updateDisplaySize(); // populates mDisplayMetrics 3585 3586 if (DEBUG) { 3587 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); 3588 } 3589 3590 updateRowStates(); 3591 mScreenPinningRequest.onConfigurationChanged(); 3592 } 3593 3594 public void userSwitched(int newUserId) { 3595 // Begin old BaseStatusBar.userSwitched 3596 setHeadsUpUser(newUserId); 3597 // End old BaseStatusBar.userSwitched 3598 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId); 3599 animateCollapsePanels(); 3600 updatePublicMode(); 3601 updateNotifications(); 3602 clearCurrentMediaNotification(); 3603 setLockscreenUser(newUserId); 3604 } 3605 3606 protected void setLockscreenUser(int newUserId) { 3607 mLockscreenWallpaper.setCurrentUser(newUserId); 3608 mScrimController.setCurrentUser(newUserId); 3609 updateMediaMetaData(true, false); 3610 } 3611 3612 /** 3613 * Reload some of our resources when the configuration changes. 3614 * 3615 * We don't reload everything when the configuration changes -- we probably 3616 * should, but getting that smooth is tough. Someday we'll fix that. In the 3617 * meantime, just update the things that we know change. 3618 */ 3619 void updateResources() { 3620 // Update the quick setting tiles 3621 if (mQSPanel != null) { 3622 mQSPanel.updateResources(); 3623 } 3624 3625 loadDimens(); 3626 3627 if (mNotificationPanel != null) { 3628 mNotificationPanel.updateResources(); 3629 } 3630 if (mBrightnessMirrorController != null) { 3631 mBrightnessMirrorController.updateResources(); 3632 } 3633 } 3634 3635 protected void loadDimens() { 3636 final Resources res = mContext.getResources(); 3637 3638 int oldBarHeight = mNaturalBarHeight; 3639 mNaturalBarHeight = res.getDimensionPixelSize( 3640 com.android.internal.R.dimen.status_bar_height); 3641 if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) { 3642 mStatusBarWindowManager.setBarHeight(mNaturalBarHeight); 3643 } 3644 mMaxAllowedKeyguardNotifications = res.getInteger( 3645 R.integer.keyguard_max_notification_count); 3646 3647 if (DEBUG) Log.v(TAG, "defineSlots"); 3648 } 3649 3650 // Visibility reporting 3651 3652 protected void handleVisibleToUserChanged(boolean visibleToUser) { 3653 if (visibleToUser) { 3654 handleVisibleToUserChangedImpl(visibleToUser); 3655 startNotificationLogging(); 3656 } else { 3657 stopNotificationLogging(); 3658 handleVisibleToUserChangedImpl(visibleToUser); 3659 } 3660 } 3661 3662 /** 3663 * The LEDs are turned off when the notification panel is shown, even just a little bit. 3664 * See also StatusBar.setPanelExpanded for another place where we attempt to do this. 3665 */ 3666 // Old BaseStatusBar.handleVisibileToUserChanged 3667 private void handleVisibleToUserChangedImpl(boolean visibleToUser) { 3668 try { 3669 if (visibleToUser) { 3670 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); 3671 boolean clearNotificationEffects = 3672 !isPanelFullyCollapsed() && 3673 (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED); 3674 int notificationLoad = mNotificationData.getActiveNotifications().size(); 3675 if (pinnedHeadsUp && isPanelFullyCollapsed()) { 3676 notificationLoad = 1; 3677 } else { 3678 MetricsLogger.histogram(mContext, "note_load", notificationLoad); 3679 } 3680 mBarService.onPanelRevealed(clearNotificationEffects, notificationLoad); 3681 } else { 3682 mBarService.onPanelHidden(); 3683 } 3684 } catch (RemoteException ex) { 3685 // Won't fail unless the world has ended. 3686 } 3687 } 3688 3689 private void stopNotificationLogging() { 3690 // Report all notifications as invisible and turn down the 3691 // reporter. 3692 if (!mCurrentlyVisibleNotifications.isEmpty()) { 3693 logNotificationVisibilityChanges(Collections.<NotificationVisibility>emptyList(), 3694 mCurrentlyVisibleNotifications); 3695 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications); 3696 } 3697 mHandler.removeCallbacks(mVisibilityReporter); 3698 mStackScroller.setChildLocationsChangedListener(null); 3699 } 3700 3701 private void startNotificationLogging() { 3702 mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener); 3703 // Some transitions like mVisibleToUser=false -> mVisibleToUser=true don't 3704 // cause the scroller to emit child location events. Hence generate 3705 // one ourselves to guarantee that we're reporting visible 3706 // notifications. 3707 // (Note that in cases where the scroller does emit events, this 3708 // additional event doesn't break anything.) 3709 mNotificationLocationsChangedListener.onChildLocationsChanged(mStackScroller); 3710 } 3711 3712 private void logNotificationVisibilityChanges( 3713 Collection<NotificationVisibility> newlyVisible, 3714 Collection<NotificationVisibility> noLongerVisible) { 3715 if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) { 3716 return; 3717 } 3718 NotificationVisibility[] newlyVisibleAr = 3719 newlyVisible.toArray(new NotificationVisibility[newlyVisible.size()]); 3720 NotificationVisibility[] noLongerVisibleAr = 3721 noLongerVisible.toArray(new NotificationVisibility[noLongerVisible.size()]); 3722 try { 3723 mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr); 3724 } catch (RemoteException e) { 3725 // Ignore. 3726 } 3727 3728 final int N = newlyVisible.size(); 3729 if (N > 0) { 3730 String[] newlyVisibleKeyAr = new String[N]; 3731 for (int i = 0; i < N; i++) { 3732 newlyVisibleKeyAr[i] = newlyVisibleAr[i].key; 3733 } 3734 3735 setNotificationsShown(newlyVisibleKeyAr); 3736 } 3737 } 3738 3739 public void onKeyguardOccludedChanged(boolean keyguardOccluded) { 3740 mNavigationBar.onKeyguardOccludedChanged(keyguardOccluded); 3741 } 3742 3743 // State logging 3744 3745 private void logStateToEventlog() { 3746 boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); 3747 boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); 3748 boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); 3749 boolean isSecure = mUnlockMethodCache.isMethodSecure(); 3750 boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer(); 3751 int stateFingerprint = getLoggingFingerprint(mState, 3752 isShowing, 3753 isOccluded, 3754 isBouncerShowing, 3755 isSecure, 3756 canSkipBouncer); 3757 if (stateFingerprint != mLastLoggedStateFingerprint) { 3758 if (mStatusBarStateLog == null) { 3759 mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); 3760 } 3761 MetricsLogger.action(mStatusBarStateLog 3762 .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) 3763 .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) 3764 .setSubtype(isSecure ? 1 : 0)); 3765 EventLogTags.writeSysuiStatusBarState(mState, 3766 isShowing ? 1 : 0, 3767 isOccluded ? 1 : 0, 3768 isBouncerShowing ? 1 : 0, 3769 isSecure ? 1 : 0, 3770 canSkipBouncer ? 1 : 0); 3771 mLastLoggedStateFingerprint = stateFingerprint; 3772 } 3773 } 3774 3775 /** 3776 * Returns a fingerprint of fields logged to eventlog 3777 */ 3778 private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, 3779 boolean keyguardOccluded, boolean bouncerShowing, boolean secure, 3780 boolean currentlyInsecure) { 3781 // Reserve 8 bits for statusBarState. We'll never go higher than 3782 // that, right? Riiiight. 3783 return (statusBarState & 0xFF) 3784 | ((keyguardShowing ? 1 : 0) << 8) 3785 | ((keyguardOccluded ? 1 : 0) << 9) 3786 | ((bouncerShowing ? 1 : 0) << 10) 3787 | ((secure ? 1 : 0) << 11) 3788 | ((currentlyInsecure ? 1 : 0) << 12); 3789 } 3790 3791 // 3792 // tracing 3793 // 3794 3795 void postStartTracing() { 3796 mHandler.postDelayed(mStartTracing, 3000); 3797 } 3798 3799 void vibrate() { 3800 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService( 3801 Context.VIBRATOR_SERVICE); 3802 vib.vibrate(250, VIBRATION_ATTRIBUTES); 3803 } 3804 3805 Runnable mStartTracing = new Runnable() { 3806 @Override 3807 public void run() { 3808 vibrate(); 3809 SystemClock.sleep(250); 3810 Log.d(TAG, "startTracing"); 3811 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace"); 3812 mHandler.postDelayed(mStopTracing, 10000); 3813 } 3814 }; 3815 3816 Runnable mStopTracing = new Runnable() { 3817 @Override 3818 public void run() { 3819 android.os.Debug.stopMethodTracing(); 3820 Log.d(TAG, "stopTracing"); 3821 vibrate(); 3822 } 3823 }; 3824 3825 @Override 3826 public void postQSRunnableDismissingKeyguard(final Runnable runnable) { 3827 mHandler.post(() -> { 3828 mLeaveOpenOnKeyguardHide = true; 3829 executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false, 3830 false); 3831 }); 3832 } 3833 3834 @Override 3835 public void postStartActivityDismissingKeyguard(final PendingIntent intent) { 3836 mHandler.post(() -> startPendingIntentDismissingKeyguard(intent)); 3837 } 3838 3839 @Override 3840 public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { 3841 mHandler.postDelayed(() -> 3842 handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/), delay); 3843 } 3844 3845 private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { 3846 startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */); 3847 } 3848 3849 private static class FastColorDrawable extends Drawable { 3850 private final int mColor; 3851 3852 public FastColorDrawable(int color) { 3853 mColor = 0xff000000 | color; 3854 } 3855 3856 @Override 3857 public void draw(Canvas canvas) { 3858 canvas.drawColor(mColor, PorterDuff.Mode.SRC); 3859 } 3860 3861 @Override 3862 public void setAlpha(int alpha) { 3863 } 3864 3865 @Override 3866 public void setColorFilter(ColorFilter colorFilter) { 3867 } 3868 3869 @Override 3870 public int getOpacity() { 3871 return PixelFormat.OPAQUE; 3872 } 3873 3874 @Override 3875 public void setBounds(int left, int top, int right, int bottom) { 3876 } 3877 3878 @Override 3879 public void setBounds(Rect bounds) { 3880 } 3881 } 3882 3883 public void destroy() { 3884 // Begin old BaseStatusBar.destroy(). 3885 mContext.unregisterReceiver(mBaseBroadcastReceiver); 3886 try { 3887 mNotificationListener.unregisterAsSystemService(); 3888 } catch (RemoteException e) { 3889 // Ignore. 3890 } 3891 mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener); 3892 // End old BaseStatusBar.destroy(). 3893 if (mStatusBarWindow != null) { 3894 mWindowManager.removeViewImmediate(mStatusBarWindow); 3895 mStatusBarWindow = null; 3896 } 3897 if (mNavigationBarView != null) { 3898 mWindowManager.removeViewImmediate(mNavigationBarView); 3899 mNavigationBarView = null; 3900 } 3901 mContext.unregisterReceiver(mBroadcastReceiver); 3902 mContext.unregisterReceiver(mDemoReceiver); 3903 mAssistManager.destroy(); 3904 3905 if (mQSPanel != null && mQSPanel.getHost() != null) { 3906 mQSPanel.getHost().destroy(); 3907 } 3908 Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null); 3909 mDeviceProvisionedController.removeCallback(mUserSetupObserver); 3910 Dependency.get(ConfigurationController.class).removeCallback(mConfigurationListener); 3911 } 3912 3913 private boolean mDemoModeAllowed; 3914 private boolean mDemoMode; 3915 3916 @Override 3917 public void dispatchDemoCommand(String command, Bundle args) { 3918 if (!mDemoModeAllowed) { 3919 mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), 3920 DEMO_MODE_ALLOWED, 0) != 0; 3921 } 3922 if (!mDemoModeAllowed) return; 3923 if (command.equals(COMMAND_ENTER)) { 3924 mDemoMode = true; 3925 } else if (command.equals(COMMAND_EXIT)) { 3926 mDemoMode = false; 3927 checkBarModes(); 3928 } else if (!mDemoMode) { 3929 // automatically enter demo mode on first demo command 3930 dispatchDemoCommand(COMMAND_ENTER, new Bundle()); 3931 } 3932 boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); 3933 if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) { 3934 mVolumeComponent.dispatchDemoCommand(command, args); 3935 } 3936 if (modeChange || command.equals(COMMAND_CLOCK)) { 3937 dispatchDemoCommandToView(command, args, R.id.clock); 3938 } 3939 if (modeChange || command.equals(COMMAND_BATTERY)) { 3940 mBatteryController.dispatchDemoCommand(command, args); 3941 } 3942 if (modeChange || command.equals(COMMAND_STATUS)) { 3943 ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args); 3944 } 3945 if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { 3946 mNetworkController.dispatchDemoCommand(command, args); 3947 } 3948 if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) { 3949 View notifications = mStatusBarView == null ? null 3950 : mStatusBarView.findViewById(R.id.notification_icon_area); 3951 if (notifications != null) { 3952 String visible = args.getString("visible"); 3953 int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; 3954 notifications.setVisibility(vis); 3955 } 3956 } 3957 if (command.equals(COMMAND_BARS)) { 3958 String mode = args.getString("mode"); 3959 int barMode = "opaque".equals(mode) ? MODE_OPAQUE : 3960 "translucent".equals(mode) ? MODE_TRANSLUCENT : 3961 "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT : 3962 "transparent".equals(mode) ? MODE_TRANSPARENT : 3963 "warning".equals(mode) ? MODE_WARNING : 3964 -1; 3965 if (barMode != -1) { 3966 boolean animate = true; 3967 if (mStatusBarView != null) { 3968 mStatusBarView.getBarTransitions().transitionTo(barMode, animate); 3969 } 3970 if (mNavigationBar != null) { 3971 mNavigationBar.getBarTransitions().transitionTo(barMode, animate); 3972 } 3973 } 3974 } 3975 } 3976 3977 private void dispatchDemoCommandToView(String command, Bundle args, int id) { 3978 if (mStatusBarView == null) return; 3979 View v = mStatusBarView.findViewById(id); 3980 if (v instanceof DemoMode) { 3981 ((DemoMode)v).dispatchDemoCommand(command, args); 3982 } 3983 } 3984 3985 /** 3986 * @return The {@link StatusBarState} the status bar is in. 3987 */ 3988 public int getBarState() { 3989 return mState; 3990 } 3991 3992 public boolean isPanelFullyCollapsed() { 3993 return mNotificationPanel.isFullyCollapsed(); 3994 } 3995 3996 public void showKeyguard() { 3997 if (mLaunchTransitionFadingAway) { 3998 mNotificationPanel.animate().cancel(); 3999 onLaunchTransitionFadingEnded(); 4000 } 4001 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 4002 if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) { 4003 setBarState(StatusBarState.FULLSCREEN_USER_SWITCHER); 4004 } else { 4005 setBarState(StatusBarState.KEYGUARD); 4006 } 4007 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 4008 if (!mDeviceInteractive) { 4009 4010 // If the screen is off already, we need to disable touch events because these might 4011 // collapse the panel after we expanded it, and thus we would end up with a blank 4012 // Keyguard. 4013 mNotificationPanel.setTouchDisabled(true); 4014 } 4015 if (mState == StatusBarState.KEYGUARD) { 4016 instantExpandNotificationsPanel(); 4017 } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) { 4018 instantCollapseNotificationPanel(); 4019 } 4020 mLeaveOpenOnKeyguardHide = false; 4021 if (mDraggedDownRow != null) { 4022 mDraggedDownRow.setUserLocked(false); 4023 mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */); 4024 mDraggedDownRow = null; 4025 } 4026 mPendingRemoteInputView = null; 4027 mAssistManager.onLockscreenShown(); 4028 } 4029 4030 private void onLaunchTransitionFadingEnded() { 4031 mNotificationPanel.setAlpha(1.0f); 4032 mNotificationPanel.onAffordanceLaunchEnded(); 4033 releaseGestureWakeLock(); 4034 runLaunchTransitionEndRunnable(); 4035 mLaunchTransitionFadingAway = false; 4036 mScrimController.forceHideScrims(false /* hide */); 4037 updateMediaMetaData(true /* metaDataChanged */, true); 4038 } 4039 4040 public boolean isCollapsing() { 4041 return mNotificationPanel.isCollapsing(); 4042 } 4043 4044 public void addPostCollapseAction(Runnable r) { 4045 mPostCollapseRunnables.add(r); 4046 } 4047 4048 public boolean isInLaunchTransition() { 4049 return mNotificationPanel.isLaunchTransitionRunning() 4050 || mNotificationPanel.isLaunchTransitionFinished(); 4051 } 4052 4053 /** 4054 * Fades the content of the keyguard away after the launch transition is done. 4055 * 4056 * @param beforeFading the runnable to be run when the circle is fully expanded and the fading 4057 * starts 4058 * @param endRunnable the runnable to be run when the transition is done 4059 */ 4060 public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, 4061 Runnable endRunnable) { 4062 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 4063 mLaunchTransitionEndRunnable = endRunnable; 4064 Runnable hideRunnable = new Runnable() { 4065 @Override 4066 public void run() { 4067 mLaunchTransitionFadingAway = true; 4068 if (beforeFading != null) { 4069 beforeFading.run(); 4070 } 4071 mScrimController.forceHideScrims(true /* hide */); 4072 updateMediaMetaData(false, true); 4073 mNotificationPanel.setAlpha(1); 4074 mStackScroller.setParentNotFullyVisible(true); 4075 mNotificationPanel.animate() 4076 .alpha(0) 4077 .setStartDelay(FADE_KEYGUARD_START_DELAY) 4078 .setDuration(FADE_KEYGUARD_DURATION) 4079 .withLayer() 4080 .withEndAction(new Runnable() { 4081 @Override 4082 public void run() { 4083 onLaunchTransitionFadingEnded(); 4084 } 4085 }); 4086 mCommandQueue.appTransitionStarting(SystemClock.uptimeMillis(), 4087 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 4088 } 4089 }; 4090 if (mNotificationPanel.isLaunchTransitionRunning()) { 4091 mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable); 4092 } else { 4093 hideRunnable.run(); 4094 } 4095 } 4096 4097 /** 4098 * Fades the content of the Keyguard while we are dozing and makes it invisible when finished 4099 * fading. 4100 */ 4101 public void fadeKeyguardWhilePulsing() { 4102 mNotificationPanel.animate() 4103 .alpha(0f) 4104 .setStartDelay(0) 4105 .setDuration(FADE_KEYGUARD_DURATION_PULSING) 4106 .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR) 4107 .start(); 4108 } 4109 4110 /** 4111 * Plays the animation when an activity that was occluding Keyguard goes away. 4112 */ 4113 public void animateKeyguardUnoccluding() { 4114 mScrimController.animateKeyguardUnoccluding(500); 4115 mNotificationPanel.setExpandedFraction(0f); 4116 animateExpandNotificationsPanel(); 4117 } 4118 4119 /** 4120 * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that 4121 * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen 4122 * because the launched app crashed or something else went wrong. 4123 */ 4124 public void startLaunchTransitionTimeout() { 4125 mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT, 4126 LAUNCH_TRANSITION_TIMEOUT_MS); 4127 } 4128 4129 private void onLaunchTransitionTimeout() { 4130 Log.w(TAG, "Launch transition: Timeout!"); 4131 mNotificationPanel.onAffordanceLaunchEnded(); 4132 releaseGestureWakeLock(); 4133 mNotificationPanel.resetViews(); 4134 } 4135 4136 private void runLaunchTransitionEndRunnable() { 4137 if (mLaunchTransitionEndRunnable != null) { 4138 Runnable r = mLaunchTransitionEndRunnable; 4139 4140 // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, 4141 // which would lead to infinite recursion. Protect against it. 4142 mLaunchTransitionEndRunnable = null; 4143 r.run(); 4144 } 4145 } 4146 4147 /** 4148 * @return true if we would like to stay in the shade, false if it should go away entirely 4149 */ 4150 public boolean hideKeyguard() { 4151 Trace.beginSection("StatusBar#hideKeyguard"); 4152 boolean staying = mLeaveOpenOnKeyguardHide; 4153 setBarState(StatusBarState.SHADE); 4154 View viewToClick = null; 4155 if (mLeaveOpenOnKeyguardHide) { 4156 mLeaveOpenOnKeyguardHide = false; 4157 long delay = calculateGoingToFullShadeDelay(); 4158 mNotificationPanel.animateToFullShade(delay); 4159 if (mDraggedDownRow != null) { 4160 mDraggedDownRow.setUserLocked(false); 4161 mDraggedDownRow = null; 4162 } 4163 viewToClick = mPendingRemoteInputView; 4164 mPendingRemoteInputView = null; 4165 4166 // Disable layout transitions in navbar for this transition because the load is just 4167 // too heavy for the CPU and GPU on any device. 4168 if (mNavigationBar != null) { 4169 mNavigationBar.disableAnimationsDuringHide(delay); 4170 } 4171 } else if (!mNotificationPanel.isCollapsing()) { 4172 instantCollapseNotificationPanel(); 4173 } 4174 updateKeyguardState(staying, false /* fromShadeLocked */); 4175 4176 if (viewToClick != null && viewToClick.isAttachedToWindow()) { 4177 viewToClick.callOnClick(); 4178 } 4179 4180 // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile 4181 // visibilities so next time we open the panel we know the correct height already. 4182 if (mQSPanel != null) { 4183 mQSPanel.refreshAllTiles(); 4184 } 4185 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); 4186 releaseGestureWakeLock(); 4187 mNotificationPanel.onAffordanceLaunchEnded(); 4188 mNotificationPanel.animate().cancel(); 4189 mNotificationPanel.setAlpha(1f); 4190 Trace.endSection(); 4191 return staying; 4192 } 4193 4194 private void releaseGestureWakeLock() { 4195 if (mGestureWakeLock.isHeld()) { 4196 mGestureWakeLock.release(); 4197 } 4198 } 4199 4200 public long calculateGoingToFullShadeDelay() { 4201 return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; 4202 } 4203 4204 /** 4205 * Notifies the status bar that Keyguard is going away very soon. 4206 */ 4207 public void keyguardGoingAway() { 4208 4209 // Treat Keyguard exit animation as an app transition to achieve nice transition for status 4210 // bar. 4211 mKeyguardGoingAway = true; 4212 mKeyguardMonitor.notifyKeyguardGoingAway(true); 4213 mCommandQueue.appTransitionPending(true); 4214 } 4215 4216 /** 4217 * Notifies the status bar the Keyguard is fading away with the specified timings. 4218 * 4219 * @param startTime the start time of the animations in uptime millis 4220 * @param delay the precalculated animation delay in miliseconds 4221 * @param fadeoutDuration the duration of the exit animation, in milliseconds 4222 */ 4223 public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { 4224 mKeyguardFadingAway = true; 4225 mKeyguardFadingAwayDelay = delay; 4226 mKeyguardFadingAwayDuration = fadeoutDuration; 4227 mWaitingForKeyguardExit = false; 4228 mCommandQueue.appTransitionStarting(startTime + fadeoutDuration 4229 - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, 4230 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 4231 recomputeDisableFlags(fadeoutDuration > 0 /* animate */); 4232 mCommandQueue.appTransitionStarting( 4233 startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, 4234 LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); 4235 mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration); 4236 } 4237 4238 public boolean isKeyguardFadingAway() { 4239 return mKeyguardFadingAway; 4240 } 4241 4242 /** 4243 * Notifies that the Keyguard fading away animation is done. 4244 */ 4245 public void finishKeyguardFadingAway() { 4246 mKeyguardFadingAway = false; 4247 mKeyguardGoingAway = false; 4248 mKeyguardMonitor.notifyKeyguardDoneFading(); 4249 } 4250 4251 public void stopWaitingForKeyguardExit() { 4252 mWaitingForKeyguardExit = false; 4253 } 4254 4255 private void updatePublicMode() { 4256 final boolean showingKeyguard = mStatusBarKeyguardViewManager.isShowing(); 4257 final boolean devicePublic = showingKeyguard 4258 && mStatusBarKeyguardViewManager.isSecure(mCurrentUserId); 4259 4260 // Look for public mode users. Users are considered public in either case of: 4261 // - device keyguard is shown in secure mode; 4262 // - profile is locked with a work challenge. 4263 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { 4264 final int userId = mCurrentProfiles.valueAt(i).id; 4265 boolean isProfilePublic = devicePublic; 4266 if (!devicePublic && userId != mCurrentUserId) { 4267 if (mStatusBarKeyguardViewManager.isSecure(userId)) { 4268 isProfilePublic = mKeyguardManager.isDeviceLocked(userId); 4269 } 4270 } 4271 setLockscreenPublicMode(isProfilePublic, userId); 4272 } 4273 } 4274 4275 protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) { 4276 Trace.beginSection("StatusBar#updateKeyguardState"); 4277 if (mState == StatusBarState.KEYGUARD) { 4278 mKeyguardIndicationController.setVisible(true); 4279 mNotificationPanel.resetViews(); 4280 if (mKeyguardUserSwitcher != null) { 4281 mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked); 4282 } 4283 mStatusBarView.removePendingHideExpandedRunnables(); 4284 } else { 4285 mKeyguardIndicationController.setVisible(false); 4286 if (mKeyguardUserSwitcher != null) { 4287 mKeyguardUserSwitcher.setKeyguard(false, 4288 goingToFullShade || 4289 mState == StatusBarState.SHADE_LOCKED || 4290 fromShadeLocked); 4291 } 4292 } 4293 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 4294 mScrimController.setKeyguardShowing(true); 4295 } else { 4296 mScrimController.setKeyguardShowing(false); 4297 } 4298 mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade); 4299 updateDozingState(); 4300 updatePublicMode(); 4301 updateStackScrollerState(goingToFullShade, fromShadeLocked); 4302 updateNotifications(); 4303 checkBarModes(); 4304 updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); 4305 mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), 4306 mStatusBarKeyguardViewManager.isSecure(), 4307 mStatusBarKeyguardViewManager.isOccluded()); 4308 Trace.endSection(); 4309 } 4310 4311 private void updateDozingState() { 4312 Trace.beginSection("StatusBar#updateDozingState"); 4313 boolean animate = !mDozing && mDozeScrimController.isPulsing(); 4314 mNotificationPanel.setDozing(mDozing, animate); 4315 mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation); 4316 mScrimController.setDozing(mDozing); 4317 mKeyguardIndicationController.setDozing(mDozing); 4318 4319 // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock 4320 // for pulsing so the Keyguard fade-out animation scrim can take over. 4321 mDozeScrimController.setDozing(mDozing && 4322 mFingerprintUnlockController.getMode() 4323 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate); 4324 updateRowStates(); 4325 Trace.endSection(); 4326 } 4327 4328 public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) { 4329 if (mStackScroller == null) return; 4330 boolean onKeyguard = mState == StatusBarState.KEYGUARD; 4331 boolean publicMode = isAnyProfilePublicMode(); 4332 mStackScroller.setHideSensitive(publicMode, goingToFullShade); 4333 mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */); 4334 mStackScroller.setExpandingEnabled(!onKeyguard); 4335 ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); 4336 mStackScroller.setActivatedChild(null); 4337 if (activatedChild != null) { 4338 activatedChild.makeInactive(false /* animate */); 4339 } 4340 } 4341 4342 public void userActivity() { 4343 if (mState == StatusBarState.KEYGUARD) { 4344 mKeyguardViewMediatorCallback.userActivity(); 4345 } 4346 } 4347 4348 public boolean interceptMediaKey(KeyEvent event) { 4349 return mState == StatusBarState.KEYGUARD 4350 && mStatusBarKeyguardViewManager.interceptMediaKey(event); 4351 } 4352 4353 protected boolean shouldUnlockOnMenuPressed() { 4354 return mDeviceInteractive && mState != StatusBarState.SHADE 4355 && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed(); 4356 } 4357 4358 public boolean onMenuPressed() { 4359 if (shouldUnlockOnMenuPressed()) { 4360 animateCollapsePanels( 4361 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); 4362 return true; 4363 } 4364 return false; 4365 } 4366 4367 public void endAffordanceLaunch() { 4368 releaseGestureWakeLock(); 4369 mNotificationPanel.onAffordanceLaunchEnded(); 4370 } 4371 4372 public boolean onBackPressed() { 4373 if (mStatusBarKeyguardViewManager.onBackPressed()) { 4374 return true; 4375 } 4376 if (mNotificationPanel.isQsExpanded()) { 4377 if (mNotificationPanel.isQsDetailShowing()) { 4378 mNotificationPanel.closeQsDetail(); 4379 } else { 4380 mNotificationPanel.animateCloseQs(); 4381 } 4382 return true; 4383 } 4384 if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { 4385 animateCollapsePanels(); 4386 return true; 4387 } 4388 if (mKeyguardUserSwitcher.hideIfNotSimple(true)) { 4389 return true; 4390 } 4391 return false; 4392 } 4393 4394 public boolean onSpacePressed() { 4395 if (mDeviceInteractive && mState != StatusBarState.SHADE) { 4396 animateCollapsePanels( 4397 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); 4398 return true; 4399 } 4400 return false; 4401 } 4402 4403 private void showBouncerIfKeyguard() { 4404 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 4405 showBouncer(); 4406 } 4407 } 4408 4409 protected void showBouncer() { 4410 mWaitingForKeyguardExit = mStatusBarKeyguardViewManager.isShowing(); 4411 mStatusBarKeyguardViewManager.dismiss(); 4412 } 4413 4414 private void instantExpandNotificationsPanel() { 4415 4416 // Make our window larger and the panel expanded. 4417 makeExpandedVisible(true); 4418 mNotificationPanel.expand(false /* animate */); 4419 } 4420 4421 private void instantCollapseNotificationPanel() { 4422 mNotificationPanel.instantCollapse(); 4423 } 4424 4425 @Override 4426 public void onActivated(ActivatableNotificationView view) { 4427 mLockscreenGestureLogger.write( 4428 MetricsEvent.ACTION_LS_NOTE, 4429 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); 4430 mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); 4431 ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); 4432 if (previousView != null) { 4433 previousView.makeInactive(true /* animate */); 4434 } 4435 mStackScroller.setActivatedChild(view); 4436 } 4437 4438 /** 4439 * @param state The {@link StatusBarState} to set. 4440 */ 4441 public void setBarState(int state) { 4442 // If we're visible and switched to SHADE_LOCKED (the user dragged 4443 // down on the lockscreen), clear notification LED, vibration, 4444 // ringing. 4445 // Other transitions are covered in handleVisibleToUserChanged(). 4446 if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED 4447 || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) { 4448 clearNotificationEffects(); 4449 } 4450 if (state == StatusBarState.KEYGUARD) { 4451 removeRemoteInputEntriesKeptUntilCollapsed(); 4452 maybeEscalateHeadsUp(); 4453 } 4454 mState = state; 4455 mGroupManager.setStatusBarState(state); 4456 mHeadsUpManager.setStatusBarState(state); 4457 mFalsingManager.setStatusBarState(state); 4458 mStatusBarWindowManager.setStatusBarState(state); 4459 mStackScroller.setStatusBarState(state); 4460 updateReportRejectedTouchVisibility(); 4461 updateDozing(); 4462 mNotificationShelf.setStatusBarState(state); 4463 } 4464 4465 @Override 4466 public void onActivationReset(ActivatableNotificationView view) { 4467 if (view == mStackScroller.getActivatedChild()) { 4468 mKeyguardIndicationController.hideTransientIndication(); 4469 mStackScroller.setActivatedChild(null); 4470 } 4471 } 4472 4473 public void onTrackingStarted() { 4474 runPostCollapseRunnables(); 4475 } 4476 4477 public void onClosingFinished() { 4478 runPostCollapseRunnables(); 4479 if (!isPanelFullyCollapsed()) { 4480 // if we set it not to be focusable when collapsing, we have to undo it when we aborted 4481 // the closing 4482 mStatusBarWindowManager.setStatusBarFocusable(true); 4483 } 4484 } 4485 4486 public void onUnlockHintStarted() { 4487 mFalsingManager.onUnlockHintStarted(); 4488 mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); 4489 } 4490 4491 public void onHintFinished() { 4492 // Delay the reset a bit so the user can read the text. 4493 mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); 4494 } 4495 4496 public void onCameraHintStarted() { 4497 mFalsingManager.onCameraHintStarted(); 4498 mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); 4499 } 4500 4501 public void onVoiceAssistHintStarted() { 4502 mFalsingManager.onLeftAffordanceHintStarted(); 4503 mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); 4504 } 4505 4506 public void onPhoneHintStarted() { 4507 mFalsingManager.onLeftAffordanceHintStarted(); 4508 mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); 4509 } 4510 4511 public void onTrackingStopped(boolean expand) { 4512 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { 4513 if (!expand && !mUnlockMethodCache.canSkipBouncer()) { 4514 showBouncerIfKeyguard(); 4515 } 4516 } 4517 } 4518 4519 protected int getMaxKeyguardNotifications(boolean recompute) { 4520 if (recompute) { 4521 mMaxKeyguardNotifications = Math.max(1, 4522 mNotificationPanel.computeMaxKeyguardNotifications( 4523 mMaxAllowedKeyguardNotifications)); 4524 return mMaxKeyguardNotifications; 4525 } 4526 return mMaxKeyguardNotifications; 4527 } 4528 4529 public int getMaxKeyguardNotifications() { 4530 return getMaxKeyguardNotifications(false /* recompute */); 4531 } 4532 4533 // TODO: Figure out way to remove this. 4534 public NavigationBarView getNavigationBarView() { 4535 return (NavigationBarView) mNavigationBar.getView(); 4536 } 4537 4538 // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ 4539 4540 4541 /* Only ever called as a consequence of a lockscreen expansion gesture. */ 4542 @Override 4543 public boolean onDraggedDown(View startingChild, int dragLengthY) { 4544 if (hasActiveNotifications() && (!isDozing() || isPulsing())) { 4545 mLockscreenGestureLogger.write( 4546 MetricsEvent.ACTION_LS_SHADE, 4547 (int) (dragLengthY / mDisplayMetrics.density), 4548 0 /* velocityDp - N/A */); 4549 4550 // We have notifications, go to locked shade. 4551 goToLockedShade(startingChild); 4552 if (startingChild instanceof ExpandableNotificationRow) { 4553 ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild; 4554 row.onExpandedByGesture(true /* drag down is always an open */); 4555 } 4556 return true; 4557 } else { 4558 // abort gesture. 4559 return false; 4560 } 4561 } 4562 4563 @Override 4564 public void onDragDownReset() { 4565 mStackScroller.setDimmed(true /* dimmed */, true /* animated */); 4566 mStackScroller.resetScrollPosition(); 4567 } 4568 4569 @Override 4570 public void onCrossedThreshold(boolean above) { 4571 mStackScroller.setDimmed(!above /* dimmed */, true /* animate */); 4572 } 4573 4574 @Override 4575 public void onTouchSlopExceeded() { 4576 mStackScroller.removeLongPressCallback(); 4577 } 4578 4579 @Override 4580 public void setEmptyDragAmount(float amount) { 4581 mNotificationPanel.setEmptyDragAmount(amount); 4582 } 4583 4584 /** 4585 * If secure with redaction: Show bouncer, go to unlocked shade. 4586 * 4587 * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p> 4588 * 4589 * @param expandView The view to expand after going to the shade. 4590 */ 4591 public void goToLockedShade(View expandView) { 4592 int userId = mCurrentUserId; 4593 ExpandableNotificationRow row = null; 4594 if (expandView instanceof ExpandableNotificationRow) { 4595 row = (ExpandableNotificationRow) expandView; 4596 row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */); 4597 // Indicate that the group expansion is changing at this time -- this way the group 4598 // and children backgrounds / divider animations will look correct. 4599 row.setGroupExpansionChanging(true); 4600 if (row.getStatusBarNotification() != null) { 4601 userId = row.getStatusBarNotification().getUserId(); 4602 } 4603 } 4604 boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId) 4605 || !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer(); 4606 if (isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { 4607 mLeaveOpenOnKeyguardHide = true; 4608 showBouncerIfKeyguard(); 4609 mDraggedDownRow = row; 4610 mPendingRemoteInputView = null; 4611 } else { 4612 mNotificationPanel.animateToFullShade(0 /* delay */); 4613 setBarState(StatusBarState.SHADE_LOCKED); 4614 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); 4615 } 4616 } 4617 4618 public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) { 4619 mLeaveOpenOnKeyguardHide = true; 4620 dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */); 4621 } 4622 4623 protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { 4624 mLeaveOpenOnKeyguardHide = true; 4625 showBouncer(); 4626 mPendingRemoteInputView = clicked; 4627 } 4628 4629 protected void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, 4630 View clickedView) { 4631 if (isKeyguardShowing()) { 4632 onLockedRemoteInput(row, clickedView); 4633 } else { 4634 row.setUserExpanded(true); 4635 row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick); 4636 } 4637 } 4638 4639 protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender, 4640 String notificationKey) { 4641 // Clear pending remote view, as we do not want to trigger pending remote input view when 4642 // it's called by other code 4643 mPendingWorkRemoteInputView = null; 4644 // Begin old BaseStatusBar.startWorkChallengeIfNecessary. 4645 final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, 4646 null, userId); 4647 if (newIntent == null) { 4648 return false; 4649 } 4650 final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); 4651 callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender); 4652 callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey); 4653 callBackIntent.setPackage(mContext.getPackageName()); 4654 4655 PendingIntent callBackPendingIntent = PendingIntent.getBroadcast( 4656 mContext, 4657 0, 4658 callBackIntent, 4659 PendingIntent.FLAG_CANCEL_CURRENT | 4660 PendingIntent.FLAG_ONE_SHOT | 4661 PendingIntent.FLAG_IMMUTABLE); 4662 newIntent.putExtra( 4663 Intent.EXTRA_INTENT, 4664 callBackPendingIntent.getIntentSender()); 4665 try { 4666 ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent, 4667 null /*options*/); 4668 } catch (RemoteException ex) { 4669 // ignore 4670 } 4671 return true; 4672 // End old BaseStatusBar.startWorkChallengeIfNecessary. 4673 } 4674 4675 protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, 4676 View clicked) { 4677 // Collapse notification and show work challenge 4678 animateCollapsePanels(); 4679 startWorkChallengeIfNecessary(userId, null, null); 4680 // Add pending remote input view after starting work challenge, as starting work challenge 4681 // will clear all previous pending review view 4682 mPendingWorkRemoteInputView = clicked; 4683 } 4684 4685 private boolean isAnyProfilePublicMode() { 4686 for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { 4687 if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { 4688 return true; 4689 } 4690 } 4691 return false; 4692 } 4693 4694 protected void onWorkChallengeChanged() { 4695 updatePublicMode(); 4696 updateNotifications(); 4697 if (mPendingWorkRemoteInputView != null && !isAnyProfilePublicMode()) { 4698 // Expand notification panel and the notification row, then click on remote input view 4699 final Runnable clickPendingViewRunnable = new Runnable() { 4700 @Override 4701 public void run() { 4702 final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView; 4703 if (pendingWorkRemoteInputView == null) { 4704 return; 4705 } 4706 4707 // Climb up the hierarchy until we get to the container for this row. 4708 ViewParent p = pendingWorkRemoteInputView.getParent(); 4709 while (!(p instanceof ExpandableNotificationRow)) { 4710 if (p == null) { 4711 return; 4712 } 4713 p = p.getParent(); 4714 } 4715 4716 final ExpandableNotificationRow row = (ExpandableNotificationRow) p; 4717 ViewParent viewParent = row.getParent(); 4718 if (viewParent instanceof NotificationStackScrollLayout) { 4719 final NotificationStackScrollLayout scrollLayout = 4720 (NotificationStackScrollLayout) viewParent; 4721 row.makeActionsVisibile(); 4722 row.post(new Runnable() { 4723 @Override 4724 public void run() { 4725 final Runnable finishScrollingCallback = new Runnable() { 4726 @Override 4727 public void run() { 4728 mPendingWorkRemoteInputView.callOnClick(); 4729 mPendingWorkRemoteInputView = null; 4730 scrollLayout.setFinishScrollingCallback(null); 4731 } 4732 }; 4733 if (scrollLayout.scrollTo(row)) { 4734 // It scrolls! So call it when it's finished. 4735 scrollLayout.setFinishScrollingCallback( 4736 finishScrollingCallback); 4737 } else { 4738 // It does not scroll, so call it now! 4739 finishScrollingCallback.run(); 4740 } 4741 } 4742 }); 4743 } 4744 } 4745 }; 4746 mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener( 4747 new ViewTreeObserver.OnGlobalLayoutListener() { 4748 @Override 4749 public void onGlobalLayout() { 4750 if (mNotificationPanel.mStatusBar.getStatusBarWindow() 4751 .getHeight() != mNotificationPanel.mStatusBar 4752 .getStatusBarHeight()) { 4753 mNotificationPanel.getViewTreeObserver() 4754 .removeOnGlobalLayoutListener(this); 4755 mNotificationPanel.post(clickPendingViewRunnable); 4756 } 4757 } 4758 }); 4759 instantExpandNotificationsPanel(); 4760 } 4761 } 4762 4763 @Override 4764 public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) { 4765 mHeadsUpManager.setExpanded(clickedEntry, nowExpanded); 4766 if (mState == StatusBarState.KEYGUARD && nowExpanded) { 4767 goToLockedShade(clickedEntry.row); 4768 } 4769 } 4770 4771 /** 4772 * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}. 4773 */ 4774 public void goToKeyguard() { 4775 if (mState == StatusBarState.SHADE_LOCKED) { 4776 mStackScroller.onGoToKeyguard(); 4777 setBarState(StatusBarState.KEYGUARD); 4778 updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/); 4779 } 4780 } 4781 4782 public long getKeyguardFadingAwayDelay() { 4783 return mKeyguardFadingAwayDelay; 4784 } 4785 4786 public long getKeyguardFadingAwayDuration() { 4787 return mKeyguardFadingAwayDuration; 4788 } 4789 4790 public void setBouncerShowing(boolean bouncerShowing) { 4791 mBouncerShowing = bouncerShowing; 4792 mStatusBarView.setBouncerShowing(bouncerShowing); 4793 recomputeDisableFlags(true /* animate */); 4794 } 4795 4796 public void onStartedGoingToSleep() { 4797 mStartedGoingToSleep = true; 4798 } 4799 4800 public void onFinishedGoingToSleep() { 4801 mNotificationPanel.onAffordanceLaunchEnded(); 4802 releaseGestureWakeLock(); 4803 mLaunchCameraOnScreenTurningOn = false; 4804 mStartedGoingToSleep = false; 4805 mDeviceInteractive = false; 4806 mWakeUpComingFromTouch = false; 4807 mWakeUpTouchLocation = null; 4808 mStackScroller.setAnimationsEnabled(false); 4809 mVisualStabilityManager.setScreenOn(false); 4810 updateVisibleToUser(); 4811 if (mLaunchCameraOnFinishedGoingToSleep) { 4812 mLaunchCameraOnFinishedGoingToSleep = false; 4813 4814 // This gets executed before we will show Keyguard, so post it in order that the state 4815 // is correct. 4816 mHandler.post(new Runnable() { 4817 @Override 4818 public void run() { 4819 onCameraLaunchGestureDetected(mLastCameraLaunchSource); 4820 } 4821 }); 4822 } 4823 } 4824 4825 public void onStartedWakingUp() { 4826 mDeviceInteractive = true; 4827 mStackScroller.setAnimationsEnabled(true); 4828 mVisualStabilityManager.setScreenOn(true); 4829 mNotificationPanel.setTouchDisabled(false); 4830 updateVisibleToUser(); 4831 } 4832 4833 public void onScreenTurningOn() { 4834 mScreenTurningOn = true; 4835 mFalsingManager.onScreenTurningOn(); 4836 mNotificationPanel.onScreenTurningOn(); 4837 if (mLaunchCameraOnScreenTurningOn) { 4838 mNotificationPanel.launchCamera(false, mLastCameraLaunchSource); 4839 mLaunchCameraOnScreenTurningOn = false; 4840 } 4841 } 4842 4843 private void vibrateForCameraGesture() { 4844 // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep. 4845 mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */); 4846 } 4847 4848 public void onScreenTurnedOn() { 4849 mScreenTurningOn = false; 4850 mDozeScrimController.onScreenTurnedOn(); 4851 } 4852 4853 @Override 4854 public void showScreenPinningRequest(int taskId) { 4855 if (mKeyguardMonitor.isShowing()) { 4856 // Don't allow apps to trigger this from keyguard. 4857 return; 4858 } 4859 // Show screen pinning request, since this comes from an app, show 'no thanks', button. 4860 showScreenPinningRequest(taskId, true); 4861 } 4862 4863 public void showScreenPinningRequest(int taskId, boolean allowCancel) { 4864 mScreenPinningRequest.showPrompt(taskId, allowCancel); 4865 } 4866 4867 public boolean hasActiveNotifications() { 4868 return !mNotificationData.getActiveNotifications().isEmpty(); 4869 } 4870 4871 public void wakeUpIfDozing(long time, View where) { 4872 if (mDozing) { 4873 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 4874 pm.wakeUp(time, "com.android.systemui:NODOZE"); 4875 mWakeUpComingFromTouch = true; 4876 where.getLocationInWindow(mTmpInt2); 4877 mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, 4878 mTmpInt2[1] + where.getHeight() / 2); 4879 mNotificationPanel.setTouchDisabled(false); 4880 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); 4881 mFalsingManager.onScreenOnFromTouch(); 4882 } 4883 } 4884 4885 @Override 4886 public void appTransitionCancelled() { 4887 EventBus.getDefault().send(new AppTransitionFinishedEvent()); 4888 } 4889 4890 @Override 4891 public void appTransitionFinished() { 4892 EventBus.getDefault().send(new AppTransitionFinishedEvent()); 4893 } 4894 4895 @Override 4896 public void onCameraLaunchGestureDetected(int source) { 4897 mLastCameraLaunchSource = source; 4898 if (mStartedGoingToSleep) { 4899 mLaunchCameraOnFinishedGoingToSleep = true; 4900 return; 4901 } 4902 if (!mNotificationPanel.canCameraGestureBeLaunched( 4903 mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) { 4904 return; 4905 } 4906 if (!mDeviceInteractive) { 4907 PowerManager pm = mContext.getSystemService(PowerManager.class); 4908 pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); 4909 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); 4910 } 4911 vibrateForCameraGesture(); 4912 if (!mStatusBarKeyguardViewManager.isShowing()) { 4913 startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, 4914 true /* dismissShade */); 4915 } else { 4916 if (!mDeviceInteractive) { 4917 // Avoid flickering of the scrim when we instant launch the camera and the bouncer 4918 // comes on. 4919 mScrimController.dontAnimateBouncerChangesUntilNextFrame(); 4920 mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); 4921 } 4922 if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) { 4923 mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source); 4924 } else { 4925 // We need to defer the camera launch until the screen comes on, since otherwise 4926 // we will dismiss us too early since we are waiting on an activity to be drawn and 4927 // incorrectly get notified because of the screen on event (which resumes and pauses 4928 // some activities) 4929 mLaunchCameraOnScreenTurningOn = true; 4930 } 4931 } 4932 } 4933 4934 @Override 4935 public void showTvPictureInPictureMenu() { 4936 // no-op. 4937 } 4938 4939 public void notifyFpAuthModeChanged() { 4940 updateDozing(); 4941 } 4942 4943 private void updateDozing() { 4944 Trace.beginSection("StatusBar#updateDozing"); 4945 // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. 4946 mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD 4947 || mFingerprintUnlockController.getMode() 4948 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; 4949 updateDozingState(); 4950 Trace.endSection(); 4951 } 4952 4953 public boolean isKeyguardShowing() { 4954 return mStatusBarKeyguardViewManager.isShowing(); 4955 } 4956 4957 private final class DozeServiceHost implements DozeHost { 4958 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 4959 4960 @Override 4961 public String toString() { 4962 return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; 4963 } 4964 4965 public void firePowerSaveChanged(boolean active) { 4966 for (Callback callback : mCallbacks) { 4967 callback.onPowerSaveChanged(active); 4968 } 4969 } 4970 4971 public void fireNotificationHeadsUp() { 4972 for (Callback callback : mCallbacks) { 4973 callback.onNotificationHeadsUp(); 4974 } 4975 } 4976 4977 @Override 4978 public void addCallback(@NonNull Callback callback) { 4979 mCallbacks.add(callback); 4980 } 4981 4982 @Override 4983 public void removeCallback(@NonNull Callback callback) { 4984 mCallbacks.remove(callback); 4985 } 4986 4987 @Override 4988 public void startDozing() { 4989 if (!mDozingRequested) { 4990 mDozingRequested = true; 4991 DozeLog.traceDozing(mContext, mDozing); 4992 updateDozing(); 4993 } 4994 } 4995 4996 @Override 4997 public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { 4998 mDozeScrimController.pulse(new PulseCallback() { 4999 5000 @Override 5001 public void onPulseStarted() { 5002 callback.onPulseStarted(); 5003 if (!mHeadsUpManager.getAllEntries().isEmpty()) { 5004 // Only pulse the stack scroller if there's actually something to show. 5005 // Otherwise just show the always-on screen. 5006 mStackScroller.setPulsing(true); 5007 mVisualStabilityManager.setPulsing(true); 5008 } 5009 } 5010 5011 @Override 5012 public void onPulseFinished() { 5013 callback.onPulseFinished(); 5014 mStackScroller.setPulsing(false); 5015 mVisualStabilityManager.setPulsing(false); 5016 } 5017 }, reason); 5018 } 5019 5020 @Override 5021 public void stopDozing() { 5022 if (mDozingRequested) { 5023 mDozingRequested = false; 5024 DozeLog.traceDozing(mContext, mDozing); 5025 updateDozing(); 5026 } 5027 } 5028 5029 @Override 5030 public void dozeTimeTick() { 5031 mKeyguardStatusView.refreshTime(); 5032 } 5033 5034 @Override 5035 public boolean isPowerSaveActive() { 5036 return mBatteryController.isPowerSave(); 5037 } 5038 5039 @Override 5040 public boolean isPulsingBlocked() { 5041 return mFingerprintUnlockController.getMode() 5042 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; 5043 } 5044 5045 @Override 5046 public void startPendingIntentDismissingKeyguard(PendingIntent intent) { 5047 StatusBar.this.startPendingIntentDismissingKeyguard(intent); 5048 } 5049 5050 } 5051 5052 public SnoozeListener getSnoozeListener() { 5053 return this; 5054 } 5055 5056 @Override 5057 public void snoozeNotification(StatusBarNotification sbn, SnoozeOption snoozeOption) { 5058 setNotificationSnoozed(sbn, snoozeOption); 5059 } 5060 5061 // Begin Extra BaseStatusBar methods. 5062 5063 protected CommandQueue mCommandQueue; 5064 protected IStatusBarService mBarService; 5065 5066 // all notifications 5067 protected NotificationData mNotificationData; 5068 protected NotificationStackScrollLayout mStackScroller; 5069 5070 protected NotificationGroupManager mGroupManager = new NotificationGroupManager(); 5071 5072 protected RemoteInputController mRemoteInputController; 5073 5074 // for heads up notifications 5075 protected HeadsUpManager mHeadsUpManager; 5076 5077 // handling reordering 5078 protected VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager(); 5079 5080 protected int mCurrentUserId = 0; 5081 final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>(); 5082 5083 protected int mLayoutDirection = -1; // invalid 5084 protected AccessibilityManager mAccessibilityManager; 5085 5086 protected boolean mDeviceInteractive; 5087 5088 protected boolean mVisible; 5089 protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>(); 5090 protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>(); 5091 5092 /** 5093 * Notifications with keys in this set are not actually around anymore. We kept them around 5094 * when they were canceled in response to a remote input interaction. This allows us to show 5095 * what you replied and allows you to continue typing into it. 5096 */ 5097 protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>(); 5098 5099 // mScreenOnFromKeyguard && mVisible. 5100 private boolean mVisibleToUser; 5101 5102 private Locale mLocale; 5103 5104 protected boolean mUseHeadsUp = false; 5105 protected boolean mHeadsUpTicker = false; 5106 protected boolean mDisableNotificationAlerts = false; 5107 5108 protected DevicePolicyManager mDevicePolicyManager; 5109 protected IDreamManager mDreamManager; 5110 protected PowerManager mPowerManager; 5111 protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; 5112 5113 // public mode, private notifications, etc 5114 private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray(); 5115 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); 5116 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray(); 5117 5118 private UserManager mUserManager; 5119 5120 protected KeyguardManager mKeyguardManager; 5121 private LockPatternUtils mLockPatternUtils; 5122 private DeviceProvisionedController mDeviceProvisionedController; 5123 5124 // UI-specific methods 5125 5126 protected WindowManager mWindowManager; 5127 protected IWindowManager mWindowManagerService; 5128 5129 protected Display mDisplay; 5130 5131 protected RecentsComponent mRecents; 5132 5133 protected int mZenMode; 5134 5135 // which notification is currently being longpress-examined by the user 5136 private NotificationGuts mNotificationGutsExposed; 5137 private MenuItem mGutsMenuItem; 5138 5139 private KeyboardShortcuts mKeyboardShortcuts; 5140 5141 protected NotificationShelf mNotificationShelf; 5142 protected DismissView mDismissView; 5143 protected EmptyShadeView mEmptyShadeView; 5144 5145 private NotificationClicker mNotificationClicker = new NotificationClicker(); 5146 5147 protected AssistManager mAssistManager; 5148 5149 protected boolean mVrMode; 5150 5151 private Set<String> mNonBlockablePkgs; 5152 5153 @Override // NotificationData.Environment 5154 public boolean isDeviceProvisioned() { 5155 return mDeviceProvisionedController.isDeviceProvisioned(); 5156 } 5157 5158 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { 5159 @Override 5160 public void onVrStateChanged(boolean enabled) { 5161 mVrMode = enabled; 5162 } 5163 }; 5164 5165 public boolean isDeviceInVrMode() { 5166 return mVrMode; 5167 } 5168 5169 private final DeviceProvisionedListener mDeviceProvisionedListener = 5170 new DeviceProvisionedListener() { 5171 @Override 5172 public void onDeviceProvisionedChanged() { 5173 updateNotifications(); 5174 } 5175 }; 5176 5177 protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { 5178 @Override 5179 public void onChange(boolean selfChange) { 5180 final int mode = Settings.Global.getInt(mContext.getContentResolver(), 5181 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF); 5182 setZenMode(mode); 5183 5184 updateLockscreenNotificationSetting(); 5185 } 5186 }; 5187 5188 private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) { 5189 @Override 5190 public void onChange(boolean selfChange) { 5191 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or 5192 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ... 5193 mUsersAllowingPrivateNotifications.clear(); 5194 mUsersAllowingNotifications.clear(); 5195 // ... and refresh all the notifications 5196 updateLockscreenNotificationSetting(); 5197 updateNotifications(); 5198 } 5199 }; 5200 5201 private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() { 5202 5203 @Override 5204 public boolean onClickHandler( 5205 final View view, final PendingIntent pendingIntent, final Intent fillInIntent) { 5206 wakeUpIfDozing(SystemClock.uptimeMillis(), view); 5207 5208 5209 if (handleRemoteInput(view, pendingIntent, fillInIntent)) { 5210 return true; 5211 } 5212 5213 if (DEBUG) { 5214 Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent); 5215 } 5216 logActionClick(view); 5217 // The intent we are sending is for the application, which 5218 // won't have permission to immediately start an activity after 5219 // the user switches to home. We know it is safe to do at this 5220 // point, so make sure new activity switches are now allowed. 5221 try { 5222 ActivityManager.getService().resumeAppSwitches(); 5223 } catch (RemoteException e) { 5224 } 5225 final boolean isActivity = pendingIntent.isActivity(); 5226 if (isActivity) { 5227 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); 5228 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( 5229 mContext, pendingIntent.getIntent(), mCurrentUserId); 5230 dismissKeyguardThenExecute(new OnDismissAction() { 5231 @Override 5232 public boolean onDismiss() { 5233 try { 5234 ActivityManager.getService().resumeAppSwitches(); 5235 } catch (RemoteException e) { 5236 } 5237 5238 boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent); 5239 5240 // close the shade if it was open 5241 if (handled) { 5242 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, 5243 true /* force */); 5244 visibilityChanged(false); 5245 mAssistManager.hideAssist(); 5246 } 5247 5248 // Wait for activity start. 5249 return handled; 5250 } 5251 }, afterKeyguardGone); 5252 return true; 5253 } else { 5254 return superOnClickHandler(view, pendingIntent, fillInIntent); 5255 } 5256 } 5257 5258 private void logActionClick(View view) { 5259 ViewParent parent = view.getParent(); 5260 String key = getNotificationKeyForParent(parent); 5261 if (key == null) { 5262 Log.w(TAG, "Couldn't determine notification for click."); 5263 return; 5264 } 5265 int index = -1; 5266 // If this is a default template, determine the index of the button. 5267 if (view.getId() == com.android.internal.R.id.action0 && 5268 parent != null && parent instanceof ViewGroup) { 5269 ViewGroup actionGroup = (ViewGroup) parent; 5270 index = actionGroup.indexOfChild(view); 5271 } 5272 try { 5273 mBarService.onNotificationActionClick(key, index); 5274 } catch (RemoteException e) { 5275 // Ignore 5276 } 5277 } 5278 5279 private String getNotificationKeyForParent(ViewParent parent) { 5280 while (parent != null) { 5281 if (parent instanceof ExpandableNotificationRow) { 5282 return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey(); 5283 } 5284 parent = parent.getParent(); 5285 } 5286 return null; 5287 } 5288 5289 private boolean superOnClickHandler(View view, PendingIntent pendingIntent, 5290 Intent fillInIntent) { 5291 return super.onClickHandler(view, pendingIntent, fillInIntent, 5292 StackId.FULLSCREEN_WORKSPACE_STACK_ID); 5293 } 5294 5295 private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) { 5296 Object tag = view.getTag(com.android.internal.R.id.remote_input_tag); 5297 RemoteInput[] inputs = null; 5298 if (tag instanceof RemoteInput[]) { 5299 inputs = (RemoteInput[]) tag; 5300 } 5301 5302 if (inputs == null) { 5303 return false; 5304 } 5305 5306 RemoteInput input = null; 5307 5308 for (RemoteInput i : inputs) { 5309 if (i.getAllowFreeFormInput()) { 5310 input = i; 5311 } 5312 } 5313 5314 if (input == null) { 5315 return false; 5316 } 5317 5318 ViewParent p = view.getParent(); 5319 RemoteInputView riv = null; 5320 while (p != null) { 5321 if (p instanceof View) { 5322 View pv = (View) p; 5323 if (pv.isRootNamespace()) { 5324 riv = findRemoteInputView(pv); 5325 break; 5326 } 5327 } 5328 p = p.getParent(); 5329 } 5330 ExpandableNotificationRow row = null; 5331 while (p != null) { 5332 if (p instanceof ExpandableNotificationRow) { 5333 row = (ExpandableNotificationRow) p; 5334 break; 5335 } 5336 p = p.getParent(); 5337 } 5338 5339 if (row == null) { 5340 return false; 5341 } 5342 5343 row.setUserExpanded(true); 5344 5345 if (!mAllowLockscreenRemoteInput) { 5346 final int userId = pendingIntent.getCreatorUserHandle().getIdentifier(); 5347 if (isLockscreenPublicMode(userId)) { 5348 onLockedRemoteInput(row, view); 5349 return true; 5350 } 5351 if (mUserManager.getUserInfo(userId).isManagedProfile() 5352 && mKeyguardManager.isDeviceLocked(userId)) { 5353 onLockedWorkRemoteInput(userId, row, view); 5354 return true; 5355 } 5356 } 5357 5358 if (riv == null) { 5359 riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild()); 5360 if (riv == null) { 5361 return false; 5362 } 5363 if (!row.getPrivateLayout().getExpandedChild().isShown()) { 5364 onMakeExpandedVisibleForRemoteInput(row, view); 5365 return true; 5366 } 5367 } 5368 5369 int width = view.getWidth(); 5370 if (view instanceof TextView) { 5371 // Center the reveal on the text which might be off-center from the TextView 5372 TextView tv = (TextView) view; 5373 if (tv.getLayout() != null) { 5374 int innerWidth = (int) tv.getLayout().getLineWidth(0); 5375 innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight(); 5376 width = Math.min(width, innerWidth); 5377 } 5378 } 5379 int cx = view.getLeft() + width / 2; 5380 int cy = view.getTop() + view.getHeight() / 2; 5381 int w = riv.getWidth(); 5382 int h = riv.getHeight(); 5383 int r = Math.max( 5384 Math.max(cx + cy, cx + (h - cy)), 5385 Math.max((w - cx) + cy, (w - cx) + (h - cy))); 5386 5387 riv.setRevealParameters(cx, cy, r); 5388 riv.setPendingIntent(pendingIntent); 5389 riv.setRemoteInput(inputs, input); 5390 riv.focusAnimated(); 5391 5392 return true; 5393 } 5394 5395 private RemoteInputView findRemoteInputView(View v) { 5396 if (v == null) { 5397 return null; 5398 } 5399 return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG); 5400 } 5401 }; 5402 5403 private final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() { 5404 @Override 5405 public void onReceive(Context context, Intent intent) { 5406 String action = intent.getAction(); 5407 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 5408 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 5409 updateCurrentProfilesCache(); 5410 if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house"); 5411 5412 updateLockscreenNotificationSetting(); 5413 5414 userSwitched(mCurrentUserId); 5415 } else if (Intent.ACTION_USER_ADDED.equals(action)) { 5416 updateCurrentProfilesCache(); 5417 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { 5418 List<ActivityManager.RecentTaskInfo> recentTask = null; 5419 try { 5420 recentTask = ActivityManager.getService().getRecentTasks(1, 5421 ActivityManager.RECENT_WITH_EXCLUDED 5422 | ActivityManager.RECENT_INCLUDE_PROFILES, 5423 mCurrentUserId).getList(); 5424 } catch (RemoteException e) { 5425 // Abandon hope activity manager not running. 5426 } 5427 if (recentTask != null && recentTask.size() > 0) { 5428 UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId); 5429 if (user != null && user.isManagedProfile()) { 5430 Toast toast = Toast.makeText(mContext, 5431 R.string.managed_profile_foreground_toast, 5432 Toast.LENGTH_SHORT); 5433 TextView text = (TextView) toast.getView().findViewById( 5434 android.R.id.message); 5435 text.setCompoundDrawablesRelativeWithIntrinsicBounds( 5436 R.drawable.stat_sys_managed_profile_status, 0, 0, 0); 5437 int paddingPx = mContext.getResources().getDimensionPixelSize( 5438 R.dimen.managed_profile_toast_padding); 5439 text.setCompoundDrawablePadding(paddingPx); 5440 toast.show(); 5441 } 5442 } 5443 } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { 5444 NotificationManager noMan = (NotificationManager) 5445 mContext.getSystemService(Context.NOTIFICATION_SERVICE); 5446 noMan.cancel(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS); 5447 5448 Settings.Secure.putInt(mContext.getContentResolver(), 5449 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); 5450 if (BANNER_ACTION_SETUP.equals(action)) { 5451 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, 5452 true /* force */); 5453 mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) 5454 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 5455 5456 ); 5457 } 5458 } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) { 5459 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT); 5460 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX); 5461 if (intentSender != null) { 5462 try { 5463 mContext.startIntentSender(intentSender, null, 0, 0, 0); 5464 } catch (IntentSender.SendIntentException e) { 5465 /* ignore */ 5466 } 5467 } 5468 if (notificationKey != null) { 5469 try { 5470 mBarService.onNotificationClick(notificationKey); 5471 } catch (RemoteException e) { 5472 /* ignore */ 5473 } 5474 } 5475 } 5476 } 5477 }; 5478 5479 private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { 5480 @Override 5481 public void onReceive(Context context, Intent intent) { 5482 final String action = intent.getAction(); 5483 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 5484 5485 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) && 5486 isCurrentProfile(getSendingUserId())) { 5487 mUsersAllowingPrivateNotifications.clear(); 5488 updateLockscreenNotificationSetting(); 5489 updateNotifications(); 5490 } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) { 5491 if (userId != mCurrentUserId && isCurrentProfile(userId)) { 5492 onWorkChallengeChanged(); 5493 } 5494 } 5495 } 5496 }; 5497 5498 private final NotificationListenerService mNotificationListener = 5499 new NotificationListenerService() { 5500 @Override 5501 public void onListenerConnected() { 5502 if (DEBUG) Log.d(TAG, "onListenerConnected"); 5503 final StatusBarNotification[] notifications = getActiveNotifications(); 5504 if (notifications == null) { 5505 Log.w(TAG, "onListenerConnected unable to get active notifications."); 5506 return; 5507 } 5508 final RankingMap currentRanking = getCurrentRanking(); 5509 mHandler.post(new Runnable() { 5510 @Override 5511 public void run() { 5512 for (StatusBarNotification sbn : notifications) { 5513 try { 5514 addNotification(sbn, currentRanking, null /* oldEntry */); 5515 } catch (InflationException e) { 5516 handleInflationException(sbn, e); 5517 } 5518 } 5519 } 5520 }); 5521 } 5522 5523 @Override 5524 public void onNotificationPosted(final StatusBarNotification sbn, 5525 final RankingMap rankingMap) { 5526 if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn); 5527 if (sbn != null) { 5528 mHandler.post(new Runnable() { 5529 @Override 5530 public void run() { 5531 processForRemoteInput(sbn.getNotification()); 5532 String key = sbn.getKey(); 5533 mKeysKeptForRemoteInput.remove(key); 5534 boolean isUpdate = mNotificationData.get(key) != null; 5535 // In case we don't allow child notifications, we ignore children of 5536 // notifications that have a summary, since we're not going to show them 5537 // anyway. This is true also when the summary is canceled, 5538 // because children are automatically canceled by NoMan in that case. 5539 if (!ENABLE_CHILD_NOTIFICATIONS 5540 && mGroupManager.isChildInGroupWithSummary(sbn)) { 5541 if (DEBUG) { 5542 Log.d(TAG, "Ignoring group child due to existing summary: " + sbn); 5543 } 5544 5545 // Remove existing notification to avoid stale data. 5546 if (isUpdate) { 5547 removeNotification(key, rankingMap); 5548 } else { 5549 mNotificationData.updateRanking(rankingMap); 5550 } 5551 return; 5552 } 5553 try { 5554 if (isUpdate) { 5555 updateNotification(sbn, rankingMap); 5556 } else { 5557 addNotification(sbn, rankingMap, null /* oldEntry */); 5558 } 5559 } catch (InflationException e) { 5560 handleInflationException(sbn, e); 5561 } 5562 } 5563 }); 5564 } 5565 } 5566 5567 @Override 5568 public void onNotificationRemoved(StatusBarNotification sbn, 5569 final RankingMap rankingMap) { 5570 if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn); 5571 if (sbn != null) { 5572 final String key = sbn.getKey(); 5573 mHandler.post(new Runnable() { 5574 @Override 5575 public void run() { 5576 removeNotification(key, rankingMap); 5577 } 5578 }); 5579 } 5580 } 5581 5582 @Override 5583 public void onNotificationRankingUpdate(final RankingMap rankingMap) { 5584 if (DEBUG) Log.d(TAG, "onRankingUpdate"); 5585 if (rankingMap != null) { 5586 mHandler.post(new Runnable() { 5587 @Override 5588 public void run() { 5589 updateNotificationRanking(rankingMap); 5590 } 5591 }); 5592 } } 5593 5594 }; 5595 5596 private void updateCurrentProfilesCache() { 5597 synchronized (mCurrentProfiles) { 5598 mCurrentProfiles.clear(); 5599 if (mUserManager != null) { 5600 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) { 5601 mCurrentProfiles.put(user.id, user); 5602 } 5603 } 5604 } 5605 } 5606 5607 protected void notifyUserAboutHiddenNotifications() { 5608 if (0 != Settings.Secure.getInt(mContext.getContentResolver(), 5609 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) { 5610 Log.d(TAG, "user hasn't seen notification about hidden notifications"); 5611 if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) { 5612 Log.d(TAG, "insecure lockscreen, skipping notification"); 5613 Settings.Secure.putInt(mContext.getContentResolver(), 5614 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); 5615 return; 5616 } 5617 Log.d(TAG, "disabling lockecreen notifications and alerting the user"); 5618 // disable lockscreen notifications until user acts on the banner. 5619 Settings.Secure.putInt(mContext.getContentResolver(), 5620 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0); 5621 Settings.Secure.putInt(mContext.getContentResolver(), 5622 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0); 5623 5624 final String packageName = mContext.getPackageName(); 5625 PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0, 5626 new Intent(BANNER_ACTION_CANCEL).setPackage(packageName), 5627 PendingIntent.FLAG_CANCEL_CURRENT); 5628 PendingIntent setupIntent = PendingIntent.getBroadcast(mContext, 0, 5629 new Intent(BANNER_ACTION_SETUP).setPackage(packageName), 5630 PendingIntent.FLAG_CANCEL_CURRENT); 5631 5632 final int colorRes = com.android.internal.R.color.system_notification_accent_color; 5633 Notification.Builder note = 5634 new Notification.Builder(mContext, NotificationChannels.GENERAL) 5635 .setSmallIcon(R.drawable.ic_android) 5636 .setContentTitle(mContext.getString( 5637 R.string.hidden_notifications_title)) 5638 .setContentText(mContext.getString(R.string.hidden_notifications_text)) 5639 .setOngoing(true) 5640 .setColor(mContext.getColor(colorRes)) 5641 .setContentIntent(setupIntent) 5642 .addAction(R.drawable.ic_close, 5643 mContext.getString(R.string.hidden_notifications_cancel), 5644 cancelIntent) 5645 .addAction(R.drawable.ic_settings, 5646 mContext.getString(R.string.hidden_notifications_setup), 5647 setupIntent); 5648 overrideNotificationAppName(mContext, note); 5649 5650 NotificationManager noMan = 5651 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 5652 noMan.notify(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS, note.build()); 5653 } 5654 } 5655 5656 @Override // NotificationData.Environment 5657 public boolean isNotificationForCurrentProfiles(StatusBarNotification n) { 5658 final int thisUserId = mCurrentUserId; 5659 final int notificationUserId = n.getUserId(); 5660 if (DEBUG && MULTIUSER_DEBUG) { 5661 Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", 5662 n, thisUserId, notificationUserId)); 5663 } 5664 return isCurrentProfile(notificationUserId); 5665 } 5666 5667 protected void setNotificationShown(StatusBarNotification n) { 5668 setNotificationsShown(new String[]{n.getKey()}); 5669 } 5670 5671 protected void setNotificationsShown(String[] keys) { 5672 try { 5673 mNotificationListener.setNotificationsShown(keys); 5674 } catch (RuntimeException e) { 5675 Log.d(TAG, "failed setNotificationsShown: ", e); 5676 } 5677 } 5678 5679 protected boolean isCurrentProfile(int userId) { 5680 synchronized (mCurrentProfiles) { 5681 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; 5682 } 5683 } 5684 5685 @Override 5686 public NotificationGroupManager getGroupManager() { 5687 return mGroupManager; 5688 } 5689 5690 public boolean isMediaNotification(NotificationData.Entry entry) { 5691 // TODO: confirm that there's a valid media key 5692 return entry.getExpandedContentView() != null && 5693 entry.getExpandedContentView() 5694 .findViewById(com.android.internal.R.id.media_actions) != null; 5695 } 5696 5697 // The (i) button in the guts that links to the system notification settings for that app 5698 private void startAppNotificationSettingsActivity(String packageName, final int appUid, 5699 final String channelId) { 5700 final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS); 5701 intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName); 5702 intent.putExtra(Settings.EXTRA_APP_UID, appUid); 5703 intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channelId); 5704 startNotificationGutsIntent(intent, appUid); 5705 } 5706 5707 private void startNotificationGutsIntent(final Intent intent, final int appUid) { 5708 dismissKeyguardThenExecute(new OnDismissAction() { 5709 @Override 5710 public boolean onDismiss() { 5711 AsyncTask.execute(new Runnable() { 5712 @Override 5713 public void run() { 5714 TaskStackBuilder.create(mContext) 5715 .addNextIntentWithParentStack(intent) 5716 .startActivities(getActivityOptions(), 5717 new UserHandle(UserHandle.getUserId(appUid))); 5718 } 5719 }); 5720 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); 5721 return true; 5722 } 5723 }, false /* afterKeyguardGone */); 5724 } 5725 5726 protected void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { 5727 if (snoozeOption.criterion != null) { 5728 mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId()); 5729 } else { 5730 mNotificationListener.snoozeNotification(sbn.getKey(), 5731 snoozeOption.snoozeForMinutes * 60 * 1000); 5732 } 5733 } 5734 5735 private void bindGuts(final ExpandableNotificationRow row, MenuItem item) { 5736 row.inflateGuts(); 5737 row.setGutsView(item); 5738 final StatusBarNotification sbn = row.getStatusBarNotification(); 5739 row.setTag(sbn.getPackageName()); 5740 final NotificationGuts guts = row.getGuts(); 5741 guts.setClosedListener((NotificationGuts g) -> { 5742 if (!g.willBeRemoved() && !row.isRemoved()) { 5743 mStackScroller.onHeightChanged(row, !isPanelFullyCollapsed() /* needsAnimation */); 5744 } 5745 mNotificationGutsExposed = null; 5746 mGutsMenuItem = null; 5747 }); 5748 5749 if (item.gutsContent instanceof SnoozeGutsContent) { 5750 ((SnoozeGutsContent) item.gutsContent).setSnoozeListener(getSnoozeListener()); 5751 ((SnoozeGutsContent) item.gutsContent).setStatusBarNotification(sbn); 5752 ((NotificationSnooze) item.gutsContent).setSnoozeOptions(row.getEntry().snoozeCriteria); 5753 } 5754 5755 if (item.gutsContent instanceof NotificationInfo) { 5756 final NotificationChannel channel = row.getEntry().channel; 5757 PackageManager pmUser = getPackageManagerForUser(mContext, 5758 sbn.getUser().getIdentifier()); 5759 final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface( 5760 ServiceManager.getService(Context.NOTIFICATION_SERVICE)); 5761 final String pkg = sbn.getPackageName(); 5762 NotificationInfo info = (NotificationInfo) item.gutsContent; 5763 final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v, 5764 int appUid) -> { 5765 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO); 5766 guts.resetFalsingCheck(); 5767 startAppNotificationSettingsActivity(pkg, appUid, channel.getId()); 5768 }; 5769 final View.OnClickListener onDoneClick = (View v) -> { 5770 // If the user has security enabled, show challenge if the setting is changed. 5771 if (info.hasImportanceChanged() 5772 && isLockscreenPublicMode(sbn.getUser().getIdentifier()) 5773 && (mState == StatusBarState.KEYGUARD 5774 || mState == StatusBarState.SHADE_LOCKED)) { 5775 OnDismissAction dismissAction = new OnDismissAction() { 5776 @Override 5777 public boolean onDismiss() { 5778 saveAndCloseNotificationMenu(info, row, guts, v); 5779 return true; 5780 } 5781 }; 5782 onLockedNotificationImportanceChange(dismissAction); 5783 } else { 5784 saveAndCloseNotificationMenu(info, row, guts, v); 5785 } 5786 }; 5787 info.bindNotification(pmUser, iNotificationManager, sbn, channel, onSettingsClick, 5788 onDoneClick, 5789 mNonBlockablePkgs); 5790 } 5791 } 5792 5793 private void saveAndCloseNotificationMenu(NotificationInfo info, 5794 ExpandableNotificationRow row, NotificationGuts guts, View done) { 5795 guts.resetFalsingCheck(); 5796 int[] rowLocation = new int[2]; 5797 int[] doneLocation = new int[2]; 5798 row.getLocationOnScreen(rowLocation); 5799 done.getLocationOnScreen(doneLocation); 5800 5801 final int centerX = done.getWidth() / 2; 5802 final int centerY = done.getHeight() / 2; 5803 final int x = doneLocation[0] - rowLocation[0] + centerX; 5804 final int y = doneLocation[1] - rowLocation[1] + centerY; 5805 dismissPopups(x, y); 5806 } 5807 5808 protected SwipeHelper.LongPressListener getNotificationLongClicker() { 5809 return new SwipeHelper.LongPressListener() { 5810 @Override 5811 public boolean onLongPress(View v, final int x, final int y, 5812 MenuItem item) { 5813 if (!(v instanceof ExpandableNotificationRow)) { 5814 return false; 5815 } 5816 if (v.getWindowToken() == null) { 5817 Log.e(TAG, "Trying to show notification guts, but not attached to window"); 5818 return false; 5819 } 5820 5821 final ExpandableNotificationRow row = (ExpandableNotificationRow) v; 5822 bindGuts(row, item); 5823 NotificationGuts guts = row.getGuts(); 5824 5825 // Assume we are a status_bar_notification_row 5826 if (guts == null) { 5827 // This view has no guts. Examples are the more card or the dismiss all view 5828 return false; 5829 } 5830 5831 // Already showing? 5832 if (guts.getVisibility() == View.VISIBLE) { 5833 dismissPopups(x, y); 5834 return false; 5835 } 5836 5837 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS); 5838 5839 // ensure that it's laid but not visible until actually laid out 5840 guts.setVisibility(View.INVISIBLE); 5841 // Post to ensure the the guts are properly laid out. 5842 guts.post(new Runnable() { 5843 @Override 5844 public void run() { 5845 if (row.getWindowToken() == null) { 5846 Log.e(TAG, "Trying to show notification guts, but not attached to " 5847 + "window"); 5848 return; 5849 } 5850 dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */, 5851 false /* animate */); 5852 guts.setVisibility(View.VISIBLE); 5853 final double horz = Math.max(guts.getWidth() - x, x); 5854 final double vert = Math.max(guts.getHeight() - y, y); 5855 final float r = (float) Math.hypot(horz, vert); 5856 final Animator a 5857 = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r); 5858 a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); 5859 a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); 5860 a.addListener(new AnimatorListenerAdapter() { 5861 @Override 5862 public void onAnimationEnd(Animator animation) { 5863 super.onAnimationEnd(animation); 5864 // Move the notification view back over the gear 5865 row.resetTranslation(); 5866 } 5867 }); 5868 a.start(); 5869 guts.setExposed(true /* exposed */, 5870 mState == StatusBarState.KEYGUARD /* needsFalsingProtection */); 5871 row.closeRemoteInput(); 5872 mStackScroller.onHeightChanged(row, true /* needsAnimation */); 5873 mNotificationGutsExposed = guts; 5874 mGutsMenuItem = item; 5875 } 5876 }); 5877 return true; 5878 } 5879 }; 5880 } 5881 5882 /** 5883 * Returns the exposed NotificationGuts or null if none are exposed. 5884 */ 5885 public NotificationGuts getExposedGuts() { 5886 return mNotificationGutsExposed; 5887 } 5888 5889 public void dismissPopups() { 5890 dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */); 5891 } 5892 5893 private void dismissPopups(int x, int y) { 5894 dismissPopups(x, y, true /* resetGear */, false /* animate */); 5895 } 5896 5897 public void dismissPopups(int x, int y, boolean resetGear, boolean animate) { 5898 if (mNotificationGutsExposed != null) { 5899 mNotificationGutsExposed.closeControls(x, y, true /* save */); 5900 } 5901 if (resetGear) { 5902 mStackScroller.resetExposedGearView(animate, true /* force */); 5903 } 5904 } 5905 5906 @Override 5907 public void toggleSplitScreen() { 5908 toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */); 5909 } 5910 5911 @Override 5912 public void preloadRecentApps() { 5913 int msg = MSG_PRELOAD_RECENT_APPS; 5914 mHandler.removeMessages(msg); 5915 mHandler.sendEmptyMessage(msg); 5916 } 5917 5918 @Override 5919 public void cancelPreloadRecentApps() { 5920 int msg = MSG_CANCEL_PRELOAD_RECENT_APPS; 5921 mHandler.removeMessages(msg); 5922 mHandler.sendEmptyMessage(msg); 5923 } 5924 5925 @Override 5926 public void dismissKeyboardShortcutsMenu() { 5927 int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU; 5928 mHandler.removeMessages(msg); 5929 mHandler.sendEmptyMessage(msg); 5930 } 5931 5932 @Override 5933 public void toggleKeyboardShortcutsMenu(int deviceId) { 5934 int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU; 5935 mHandler.removeMessages(msg); 5936 mHandler.obtainMessage(msg, deviceId, 0).sendToTarget(); 5937 } 5938 5939 protected void sendCloseSystemWindows(String reason) { 5940 try { 5941 ActivityManager.getService().closeSystemDialogs(reason); 5942 } catch (RemoteException e) { 5943 } 5944 } 5945 5946 protected void toggleKeyboardShortcuts(int deviceId) { 5947 KeyboardShortcuts.toggle(mContext, deviceId); 5948 } 5949 5950 protected void dismissKeyboardShortcuts() { 5951 KeyboardShortcuts.dismiss(); 5952 } 5953 5954 /** 5955 * Save the current "public" (locked and secure) state of the lockscreen. 5956 */ 5957 public void setLockscreenPublicMode(boolean publicMode, int userId) { 5958 mLockscreenPublicMode.put(userId, publicMode); 5959 } 5960 5961 public boolean isLockscreenPublicMode(int userId) { 5962 return mLockscreenPublicMode.get(userId, false); 5963 } 5964 5965 /** 5966 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in 5967 * "public" (secure & locked) mode? 5968 */ 5969 public boolean userAllowsNotificationsInPublic(int userHandle) { 5970 if (userHandle == UserHandle.USER_ALL) { 5971 return true; 5972 } 5973 5974 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) { 5975 final boolean allowed = 0 != Settings.Secure.getIntForUser( 5976 mContext.getContentResolver(), 5977 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle); 5978 mUsersAllowingNotifications.append(userHandle, allowed); 5979 return allowed; 5980 } 5981 5982 return mUsersAllowingNotifications.get(userHandle); 5983 } 5984 5985 /** 5986 * Has the given user chosen to allow their private (full) notifications to be shown even 5987 * when the lockscreen is in "public" (secure & locked) mode? 5988 */ 5989 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) { 5990 if (userHandle == UserHandle.USER_ALL) { 5991 return true; 5992 } 5993 5994 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) { 5995 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser( 5996 mContext.getContentResolver(), 5997 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle); 5998 final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle); 5999 final boolean allowed = allowedByUser && allowedByDpm; 6000 mUsersAllowingPrivateNotifications.append(userHandle, allowed); 6001 return allowed; 6002 } 6003 6004 return mUsersAllowingPrivateNotifications.get(userHandle); 6005 } 6006 6007 private boolean adminAllowsUnredactedNotifications(int userHandle) { 6008 if (userHandle == UserHandle.USER_ALL) { 6009 return true; 6010 } 6011 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, 6012 userHandle); 6013 return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0; 6014 } 6015 6016 /** 6017 * Returns true if we're on a secure lockscreen and the user wants to hide notification data. 6018 * If so, notifications should be hidden. 6019 */ 6020 @Override // NotificationData.Environment 6021 public boolean shouldHideNotifications(int userId) { 6022 return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId) 6023 || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId)); 6024 } 6025 6026 /** 6027 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via 6028 * package-specific override. 6029 */ 6030 @Override // NotificationDate.Environment 6031 public boolean shouldHideNotifications(String key) { 6032 return isLockscreenPublicMode(mCurrentUserId) 6033 && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET; 6034 } 6035 6036 /** 6037 * Returns true if we're on a secure lockscreen. 6038 */ 6039 @Override // NotificationData.Environment 6040 public boolean isSecurelyLocked(int userId) { 6041 return isLockscreenPublicMode(userId); 6042 } 6043 6044 public void onNotificationClear(StatusBarNotification notification) { 6045 try { 6046 mBarService.onNotificationClear( 6047 notification.getPackageName(), 6048 notification.getTag(), 6049 notification.getId(), 6050 notification.getUserId()); 6051 } catch (android.os.RemoteException ex) { 6052 // oh well 6053 } 6054 } 6055 6056 /** 6057 * Called when the notification panel layouts 6058 */ 6059 public void onPanelLaidOut() { 6060 if (mState == StatusBarState.KEYGUARD) { 6061 // Since the number of notifications is determined based on the height of the view, we 6062 // need to update them. 6063 int maxBefore = getMaxKeyguardNotifications(false /* recompute */); 6064 int maxNotifications = getMaxKeyguardNotifications(true /* recompute */); 6065 if (maxBefore != maxNotifications) { 6066 updateRowStates(); 6067 } 6068 } 6069 } 6070 6071 protected void inflateViews(Entry entry, ViewGroup parent) throws 6072 InflationException { 6073 PackageManager pmUser = getPackageManagerForUser(mContext, 6074 entry.notification.getUser().getIdentifier()); 6075 6076 final StatusBarNotification sbn = entry.notification; 6077 ExpandableNotificationRow row; 6078 if (entry.row != null) { 6079 row = entry.row; 6080 entry.reset(); 6081 } else { 6082 // create the row view 6083 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 6084 Context.LAYOUT_INFLATER_SERVICE); 6085 row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row, 6086 parent, false); 6087 row.setExpansionLogger(this, entry.notification.getKey()); 6088 row.setGroupManager(mGroupManager); 6089 row.setHeadsUpManager(mHeadsUpManager); 6090 row.setRemoteInputController(mRemoteInputController); 6091 row.setOnExpandClickListener(this); 6092 row.setRemoteViewClickHandler(mOnClickHandler); 6093 row.setInflateExceptionHandler(mInflationExceptionHandler); 6094 6095 // Get the app name. 6096 // Note that Notification.Builder#bindHeaderAppName has similar logic 6097 // but since this field is used in the guts, it must be accurate. 6098 // Therefore we will only show the application label, or, failing that, the 6099 // package name. No substitutions. 6100 final String pkg = sbn.getPackageName(); 6101 String appname = pkg; 6102 try { 6103 final ApplicationInfo info = pmUser.getApplicationInfo(pkg, 6104 PackageManager.MATCH_UNINSTALLED_PACKAGES 6105 | PackageManager.MATCH_DISABLED_COMPONENTS); 6106 if (info != null) { 6107 appname = String.valueOf(pmUser.getApplicationLabel(info)); 6108 } 6109 } catch (NameNotFoundException e) { 6110 // Do nothing 6111 } 6112 row.setAppName(appname); 6113 row.setOnDismissRunnable(() -> 6114 performRemoveNotification(row.getStatusBarNotification())); 6115 row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 6116 if (ENABLE_REMOTE_INPUT) { 6117 row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 6118 } 6119 } 6120 6121 boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey()); 6122 row.setIsLowPriority(isLowPriority); 6123 // bind the click event to the content area 6124 mNotificationClicker.register(row, sbn); 6125 6126 // Extract target SDK version. 6127 try { 6128 ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0); 6129 entry.targetSdk = info.targetSdkVersion; 6130 } catch (NameNotFoundException ex) { 6131 Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex); 6132 } 6133 row.setLegacy(entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD 6134 && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP); 6135 entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP); 6136 entry.autoRedacted = entry.notification.getNotification().publicVersion == null; 6137 6138 entry.row = row; 6139 entry.row.setOnActivatedListener(this); 6140 6141 boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn, 6142 mNotificationData.getImportance(sbn.getKey())); 6143 boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && mPanelExpanded; 6144 row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight); 6145 row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp); 6146 row.updateNotification(entry); 6147 } 6148 6149 /** 6150 * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this 6151 * via first-class API. 6152 * 6153 * TODO: Remove once enough apps specify remote inputs on their own. 6154 */ 6155 private void processForRemoteInput(Notification n) { 6156 if (!ENABLE_REMOTE_INPUT) return; 6157 6158 if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") && 6159 (n.actions == null || n.actions.length == 0)) { 6160 Notification.Action viableAction = null; 6161 Notification.WearableExtender we = new Notification.WearableExtender(n); 6162 6163 List<Notification.Action> actions = we.getActions(); 6164 final int numActions = actions.size(); 6165 6166 for (int i = 0; i < numActions; i++) { 6167 Notification.Action action = actions.get(i); 6168 if (action == null) { 6169 continue; 6170 } 6171 RemoteInput[] remoteInputs = action.getRemoteInputs(); 6172 if (remoteInputs == null) { 6173 continue; 6174 } 6175 for (RemoteInput ri : remoteInputs) { 6176 if (ri.getAllowFreeFormInput()) { 6177 viableAction = action; 6178 break; 6179 } 6180 } 6181 if (viableAction != null) { 6182 break; 6183 } 6184 } 6185 6186 if (viableAction != null) { 6187 Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n); 6188 rebuilder.setActions(viableAction); 6189 rebuilder.build(); // will rewrite n 6190 } 6191 } 6192 } 6193 6194 public void startPendingIntentDismissingKeyguard(final PendingIntent intent) { 6195 if (!isDeviceProvisioned()) return; 6196 6197 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); 6198 final boolean afterKeyguardGone = intent.isActivity() 6199 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), 6200 mCurrentUserId); 6201 dismissKeyguardThenExecute(new OnDismissAction() { 6202 @Override 6203 public boolean onDismiss() { 6204 new Thread() { 6205 @Override 6206 public void run() { 6207 try { 6208 // The intent we are sending is for the application, which 6209 // won't have permission to immediately start an activity after 6210 // the user switches to home. We know it is safe to do at this 6211 // point, so make sure new activity switches are now allowed. 6212 ActivityManager.getService().resumeAppSwitches(); 6213 } catch (RemoteException e) { 6214 } 6215 try { 6216 intent.send(null, 0, null, null, null, null, getActivityOptions()); 6217 } catch (PendingIntent.CanceledException e) { 6218 // the stack trace isn't very helpful here. 6219 // Just log the exception message. 6220 Log.w(TAG, "Sending intent failed: " + e); 6221 6222 // TODO: Dismiss Keyguard. 6223 } 6224 if (intent.isActivity()) { 6225 mAssistManager.hideAssist(); 6226 } 6227 } 6228 }.start(); 6229 6230 // close the shade if it was open 6231 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, 6232 true /* force */, true /* delayed */); 6233 visibilityChanged(false); 6234 6235 return true; 6236 } 6237 }, afterKeyguardGone); 6238 } 6239 6240 6241 private final class NotificationClicker implements View.OnClickListener { 6242 6243 @Override 6244 public void onClick(final View v) { 6245 if (!(v instanceof ExpandableNotificationRow)) { 6246 Log.e(TAG, "NotificationClicker called on a view that is not a notification row."); 6247 return; 6248 } 6249 6250 wakeUpIfDozing(SystemClock.uptimeMillis(), v); 6251 6252 final ExpandableNotificationRow row = (ExpandableNotificationRow) v; 6253 final StatusBarNotification sbn = row.getStatusBarNotification(); 6254 if (sbn == null) { 6255 Log.e(TAG, "NotificationClicker called on an unclickable notification,"); 6256 return; 6257 } 6258 6259 // Check if the notification is displaying the gear, if so slide notification back 6260 if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) { 6261 row.animateTranslateNotification(0); 6262 return; 6263 } 6264 6265 Notification notification = sbn.getNotification(); 6266 final PendingIntent intent = notification.contentIntent != null 6267 ? notification.contentIntent 6268 : notification.fullScreenIntent; 6269 final String notificationKey = sbn.getKey(); 6270 6271 // Mark notification for one frame. 6272 row.setJustClicked(true); 6273 DejankUtils.postAfterTraversal(new Runnable() { 6274 @Override 6275 public void run() { 6276 row.setJustClicked(false); 6277 } 6278 }); 6279 6280 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); 6281 final boolean afterKeyguardGone = intent.isActivity() 6282 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), 6283 mCurrentUserId); 6284 dismissKeyguardThenExecute(new OnDismissAction() { 6285 @Override 6286 public boolean onDismiss() { 6287 if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) { 6288 // Release the HUN notification to the shade. 6289 6290 if (isPanelFullyCollapsed()) { 6291 HeadsUpManager.setIsClickedNotification(row, true); 6292 } 6293 // 6294 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will 6295 // become canceled shortly by NoMan, but we can't assume that. 6296 mHeadsUpManager.releaseImmediately(notificationKey); 6297 } 6298 StatusBarNotification parentToCancel = null; 6299 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) { 6300 StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn) 6301 .getStatusBarNotification(); 6302 if (shouldAutoCancel(summarySbn)) { 6303 parentToCancel = summarySbn; 6304 } 6305 } 6306 final StatusBarNotification parentToCancelFinal = parentToCancel; 6307 new Thread() { 6308 @Override 6309 public void run() { 6310 try { 6311 // The intent we are sending is for the application, which 6312 // won't have permission to immediately start an activity after 6313 // the user switches to home. We know it is safe to do at this 6314 // point, so make sure new activity switches are now allowed. 6315 ActivityManager.getService().resumeAppSwitches(); 6316 } catch (RemoteException e) { 6317 } 6318 if (intent != null) { 6319 // If we are launching a work activity and require to launch 6320 // separate work challenge, we defer the activity action and cancel 6321 // notification until work challenge is unlocked. 6322 if (intent.isActivity()) { 6323 final int userId = intent.getCreatorUserHandle() 6324 .getIdentifier(); 6325 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) 6326 && mKeyguardManager.isDeviceLocked(userId)) { 6327 boolean canBypass = false; 6328 try { 6329 canBypass = ActivityManager.getService() 6330 .canBypassWorkChallenge(intent); 6331 } catch (RemoteException e) { 6332 } 6333 // For direct-boot aware activities, they can be shown when 6334 // the device is still locked without triggering the work 6335 // challenge. 6336 if ((!canBypass) && startWorkChallengeIfNecessary(userId, 6337 intent.getIntentSender(), notificationKey)) { 6338 // Show work challenge, do not run PendingIntent and 6339 // remove notification 6340 return; 6341 } 6342 } 6343 } 6344 try { 6345 intent.send(null, 0, null, null, null, null, 6346 getActivityOptions()); 6347 } catch (PendingIntent.CanceledException e) { 6348 // the stack trace isn't very helpful here. 6349 // Just log the exception message. 6350 Log.w(TAG, "Sending contentIntent failed: " + e); 6351 6352 // TODO: Dismiss Keyguard. 6353 } 6354 if (intent.isActivity()) { 6355 mAssistManager.hideAssist(); 6356 } 6357 } 6358 6359 try { 6360 mBarService.onNotificationClick(notificationKey); 6361 } catch (RemoteException ex) { 6362 // system process is dead if we're here. 6363 } 6364 if (parentToCancelFinal != null) { 6365 // We have to post it to the UI thread for synchronization 6366 mHandler.post(new Runnable() { 6367 @Override 6368 public void run() { 6369 Runnable removeRunnable = new Runnable() { 6370 @Override 6371 public void run() { 6372 performRemoveNotification(parentToCancelFinal); 6373 } 6374 }; 6375 if (isCollapsing()) { 6376 // To avoid lags we're only performing the remove 6377 // after the shade was collapsed 6378 addPostCollapseAction(removeRunnable); 6379 } else { 6380 removeRunnable.run(); 6381 } 6382 } 6383 }); 6384 } 6385 } 6386 }.start(); 6387 6388 // close the shade if it was open 6389 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, 6390 true /* force */, true /* delayed */); 6391 visibilityChanged(false); 6392 6393 return true; 6394 } 6395 }, afterKeyguardGone); 6396 } 6397 6398 private boolean shouldAutoCancel(StatusBarNotification sbn) { 6399 int flags = sbn.getNotification().flags; 6400 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) { 6401 return false; 6402 } 6403 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) { 6404 return false; 6405 } 6406 return true; 6407 } 6408 6409 public void register(ExpandableNotificationRow row, StatusBarNotification sbn) { 6410 Notification notification = sbn.getNotification(); 6411 if (notification.contentIntent != null || notification.fullScreenIntent != null) { 6412 row.setOnClickListener(this); 6413 } else { 6414 row.setOnClickListener(null); 6415 } 6416 } 6417 } 6418 6419 protected Bundle getActivityOptions() { 6420 // Anything launched from the notification shade should always go into the 6421 // fullscreen stack. 6422 ActivityOptions options = ActivityOptions.makeBasic(); 6423 options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID); 6424 return options.toBundle(); 6425 } 6426 6427 protected void visibilityChanged(boolean visible) { 6428 if (mVisible != visible) { 6429 mVisible = visible; 6430 if (!visible) { 6431 dismissPopups(); 6432 } 6433 } 6434 updateVisibleToUser(); 6435 } 6436 6437 protected void updateVisibleToUser() { 6438 boolean oldVisibleToUser = mVisibleToUser; 6439 mVisibleToUser = mVisible && mDeviceInteractive; 6440 6441 if (oldVisibleToUser != mVisibleToUser) { 6442 handleVisibleToUserChanged(mVisibleToUser); 6443 } 6444 } 6445 6446 /** 6447 * Clear Buzz/Beep/Blink. 6448 */ 6449 public void clearNotificationEffects() { 6450 try { 6451 mBarService.clearNotificationEffects(); 6452 } catch (RemoteException e) { 6453 // Won't fail unless the world has ended. 6454 } 6455 } 6456 6457 /** 6458 * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService 6459 * about the failure. 6460 * 6461 * WARNING: this will call back into us. Don't hold any locks. 6462 */ 6463 void handleNotificationError(StatusBarNotification n, String message) { 6464 removeNotification(n.getKey(), null); 6465 try { 6466 mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(), 6467 n.getInitialPid(), message, n.getUserId()); 6468 } catch (RemoteException ex) { 6469 // The end is nigh. 6470 } 6471 } 6472 6473 protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) { 6474 NotificationData.Entry entry = mNotificationData.remove(key, ranking); 6475 if (entry == null) { 6476 Log.w(TAG, "removeNotification for unknown key: " + key); 6477 return null; 6478 } 6479 updateNotifications(); 6480 Dependency.get(LeakDetector.class).trackGarbage(entry); 6481 return entry.notification; 6482 } 6483 6484 protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) 6485 throws InflationException { 6486 if (DEBUG) { 6487 Log.d(TAG, "createNotificationViews(notification=" + sbn); 6488 } 6489 NotificationData.Entry entry = new NotificationData.Entry(sbn); 6490 Dependency.get(LeakDetector.class).trackInstance(entry); 6491 entry.createIcons(mContext, sbn); 6492 6493 // Construct the expanded view. 6494 inflateViews(entry, mStackScroller); 6495 return entry; 6496 } 6497 6498 protected void addNotificationViews(Entry entry, RankingMap ranking) { 6499 if (entry == null) { 6500 return; 6501 } 6502 // Add the expanded view and icon. 6503 mNotificationData.add(entry, ranking); 6504 updateNotifications(); 6505 } 6506 6507 /** 6508 * Updates expanded, dimmed and locked states of notification rows. 6509 */ 6510 protected void updateRowStates() { 6511 final int N = mStackScroller.getChildCount(); 6512 6513 int visibleNotifications = 0; 6514 boolean onKeyguard = mState == StatusBarState.KEYGUARD; 6515 int maxNotifications = -1; 6516 if (onKeyguard) { 6517 maxNotifications = getMaxKeyguardNotifications(true /* recompute */); 6518 } 6519 mStackScroller.setMaxDisplayedNotifications(maxNotifications); 6520 Stack<ExpandableNotificationRow> stack = new Stack<>(); 6521 for (int i = N - 1; i >= 0; i--) { 6522 View child = mStackScroller.getChildAt(i); 6523 if (!(child instanceof ExpandableNotificationRow)) { 6524 continue; 6525 } 6526 stack.push((ExpandableNotificationRow) child); 6527 } 6528 while(!stack.isEmpty()) { 6529 ExpandableNotificationRow row = stack.pop(); 6530 NotificationData.Entry entry = row.getEntry(); 6531 boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification); 6532 if (onKeyguard) { 6533 row.setOnKeyguard(true); 6534 } else { 6535 row.setOnKeyguard(false); 6536 row.setSystemExpanded(visibleNotifications == 0 && !childNotification); 6537 } 6538 entry.row.setShowAmbient(isDozing()); 6539 int userId = entry.notification.getUserId(); 6540 boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup( 6541 entry.notification) && !entry.row.isRemoved(); 6542 boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification); 6543 if (suppressedSummary 6544 || (isLockscreenPublicMode(userId) && !mShowLockscreenNotifications) 6545 || (onKeyguard && !showOnKeyguard)) { 6546 entry.row.setVisibility(View.GONE); 6547 } else { 6548 boolean wasGone = entry.row.getVisibility() == View.GONE; 6549 if (wasGone) { 6550 entry.row.setVisibility(View.VISIBLE); 6551 } 6552 if (!childNotification && !entry.row.isRemoved()) { 6553 if (wasGone) { 6554 // notify the scroller of a child addition 6555 mStackScroller.generateAddAnimation(entry.row, 6556 !showOnKeyguard /* fromMoreCard */); 6557 } 6558 visibleNotifications++; 6559 } 6560 } 6561 if (row.isSummaryWithChildren()) { 6562 List<ExpandableNotificationRow> notificationChildren = 6563 row.getNotificationChildren(); 6564 int size = notificationChildren.size(); 6565 for (int i = size - 1; i >= 0; i--) { 6566 stack.push(notificationChildren.get(i)); 6567 } 6568 } 6569 } 6570 mNotificationPanel.setNoVisibleNotifications(visibleNotifications == 0); 6571 6572 mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1); 6573 mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2); 6574 mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - 3); 6575 } 6576 6577 public boolean shouldShowOnKeyguard(StatusBarNotification sbn) { 6578 return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey()); 6579 } 6580 6581 // extended in StatusBar 6582 protected void setShowLockscreenNotifications(boolean show) { 6583 mShowLockscreenNotifications = show; 6584 } 6585 6586 protected void setLockScreenAllowRemoteInput(boolean allowLockscreenRemoteInput) { 6587 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput; 6588 } 6589 6590 private void updateLockscreenNotificationSetting() { 6591 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(), 6592 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 6593 1, 6594 mCurrentUserId) != 0; 6595 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures( 6596 null /* admin */, mCurrentUserId); 6597 final boolean allowedByDpm = (dpmFlags 6598 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0; 6599 6600 setShowLockscreenNotifications(show && allowedByDpm); 6601 6602 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) { 6603 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(), 6604 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, 6605 0, 6606 mCurrentUserId) != 0; 6607 final boolean remoteInputDpm = 6608 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0; 6609 6610 setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm); 6611 } else { 6612 setLockScreenAllowRemoteInput(false); 6613 } 6614 } 6615 6616 public void updateNotification(StatusBarNotification notification, RankingMap ranking) 6617 throws InflationException { 6618 if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); 6619 6620 final String key = notification.getKey(); 6621 Entry entry = mNotificationData.get(key); 6622 if (entry == null) { 6623 return; 6624 } else { 6625 mHeadsUpEntriesToRemoveOnSwitch.remove(entry); 6626 mRemoteInputEntriesToRemoveOnCollapse.remove(entry); 6627 } 6628 6629 Notification n = notification.getNotification(); 6630 mNotificationData.updateRanking(ranking); 6631 6632 final StatusBarNotification oldNotification = entry.notification; 6633 entry.notification = notification; 6634 mGroupManager.onEntryUpdated(entry, oldNotification); 6635 6636 entry.updateIcons(mContext, n); 6637 inflateViews(entry, mStackScroller); 6638 6639 boolean shouldPeek = shouldPeek(entry, notification); 6640 boolean alertAgain = alertAgain(entry, n); 6641 6642 updateHeadsUp(key, entry, shouldPeek, alertAgain); 6643 updateNotifications(); 6644 6645 if (!notification.isClearable()) { 6646 // The user may have performed a dismiss action on the notification, since it's 6647 // not clearable we should snap it back. 6648 mStackScroller.snapViewIfNeeded(entry.row); 6649 } 6650 6651 if (DEBUG) { 6652 // Is this for you? 6653 boolean isForCurrentUser = isNotificationForCurrentProfiles(notification); 6654 Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you"); 6655 } 6656 setAreThereNotifications(); 6657 } 6658 6659 protected void updatePublicContentView(Entry entry, 6660 StatusBarNotification sbn) { 6661 final RemoteViews publicContentView = entry.cachedPublicContentView; 6662 View inflatedView = entry.getPublicContentView(); 6663 if (entry.autoRedacted && publicContentView != null && inflatedView != null) { 6664 final boolean disabledByPolicy = 6665 !adminAllowsUnredactedNotifications(entry.notification.getUserId()); 6666 String notificationHiddenText = mContext.getString(disabledByPolicy 6667 ? com.android.internal.R.string.notification_hidden_by_policy_text 6668 : com.android.internal.R.string.notification_hidden_text); 6669 TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title); 6670 if (titleView != null 6671 && !titleView.getText().toString().equals(notificationHiddenText)) { 6672 titleView.setText(notificationHiddenText); 6673 } 6674 } 6675 } 6676 6677 protected void notifyHeadsUpScreenOff() { 6678 maybeEscalateHeadsUp(); 6679 } 6680 6681 private boolean alertAgain(Entry oldEntry, Notification newNotification) { 6682 return oldEntry == null || !oldEntry.hasInterrupted() 6683 || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0; 6684 } 6685 6686 protected boolean shouldPeek(Entry entry) { 6687 return shouldPeek(entry, entry.notification); 6688 } 6689 6690 protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) { 6691 if (!mUseHeadsUp || isDeviceInVrMode()) { 6692 return false; 6693 } 6694 6695 if (mNotificationData.shouldFilterOut(sbn)) { 6696 if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey()); 6697 return false; 6698 } 6699 6700 boolean inUse = mPowerManager.isScreenOn(); 6701 try { 6702 inUse = inUse && !mDreamManager.isDreaming(); 6703 } catch (RemoteException e) { 6704 Log.d(TAG, "failed to query dream manager", e); 6705 } 6706 6707 if (!inUse && !isDozing()) { 6708 if (DEBUG) { 6709 Log.d(TAG, "No peeking: not in use: " + sbn.getKey()); 6710 } 6711 return false; 6712 } 6713 6714 if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) { 6715 if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey()); 6716 return false; 6717 } 6718 6719 if (entry.hasJustLaunchedFullScreenIntent()) { 6720 if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey()); 6721 return false; 6722 } 6723 6724 if (isSnoozedPackage(sbn)) { 6725 if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey()); 6726 return false; 6727 } 6728 6729 // Allow peeking for DEFAULT notifications only if we're on Ambient Display. 6730 int importanceLevel = isDozing() ? NotificationManager.IMPORTANCE_DEFAULT 6731 : NotificationManager.IMPORTANCE_HIGH; 6732 if (mNotificationData.getImportance(sbn.getKey()) < importanceLevel) { 6733 if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey()); 6734 return false; 6735 } 6736 6737 if (sbn.getNotification().fullScreenIntent != null) { 6738 if (mAccessibilityManager.isTouchExplorationEnabled()) { 6739 if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey()); 6740 return false; 6741 } else { 6742 // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent 6743 return !mStatusBarKeyguardViewManager.isShowing() 6744 || mStatusBarKeyguardViewManager.isOccluded(); 6745 } 6746 } 6747 6748 return true; 6749 } 6750 6751 /** 6752 * @return Whether the security bouncer from Keyguard is showing. 6753 */ 6754 public boolean isBouncerShowing() { 6755 return mBouncerShowing; 6756 } 6757 6758 /** 6759 * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then 6760 * return PackageManager for mContext 6761 */ 6762 public static PackageManager getPackageManagerForUser(Context context, int userId) { 6763 Context contextForUser = context; 6764 // UserHandle defines special userId as negative values, e.g. USER_ALL 6765 if (userId >= 0) { 6766 try { 6767 // Create a context for the correct user so if a package isn't installed 6768 // for user 0 we can still load information about the package. 6769 contextForUser = 6770 context.createPackageContextAsUser(context.getPackageName(), 6771 Context.CONTEXT_RESTRICTED, 6772 new UserHandle(userId)); 6773 } catch (NameNotFoundException e) { 6774 // Shouldn't fail to find the package name for system ui. 6775 } 6776 } 6777 return contextForUser.getPackageManager(); 6778 } 6779 6780 @Override 6781 public void logNotificationExpansion(String key, boolean userAction, boolean expanded) { 6782 try { 6783 mBarService.onNotificationExpansionChanged(key, userAction, expanded); 6784 } catch (RemoteException e) { 6785 // Ignore. 6786 } 6787 } 6788 6789 public boolean isKeyguardSecure() { 6790 if (mStatusBarKeyguardViewManager == null) { 6791 // startKeyguard() hasn't been called yet, so we don't know. 6792 // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this 6793 // value onVisibilityChanged(). 6794 Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false", 6795 new Throwable()); 6796 return false; 6797 } 6798 return mStatusBarKeyguardViewManager.isSecure(); 6799 } 6800 6801 @Override 6802 public void showAssistDisclosure() { 6803 if (mAssistManager != null) { 6804 mAssistManager.showDisclosure(); 6805 } 6806 } 6807 6808 @Override 6809 public void startAssist(Bundle args) { 6810 if (mAssistManager != null) { 6811 mAssistManager.startAssist(args); 6812 } 6813 } 6814 // End Extra BaseStatusBarMethods. 6815} 6816