blob: 0fd0dabbc3f2419a2d1a86d5bceece2cbd9473cf [file] [log] [blame]
Jason Monk297c04e2018-08-23 17:16:59 -04001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.statusbar.phone;
16
Jason Monk297c04e2018-08-23 17:16:59 -040017import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
18import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
19import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
20import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
Jason Monk297c04e2018-08-23 17:16:59 -040021
Ned Burns1dd6b402019-01-02 15:25:23 -050022import android.annotation.Nullable;
Jason Monk297c04e2018-08-23 17:16:59 -040023import android.app.KeyguardManager;
Jason Monk297c04e2018-08-23 17:16:59 -040024import android.content.Context;
Jason Monk297c04e2018-08-23 17:16:59 -040025import android.content.pm.PackageManager;
Jason Monk297c04e2018-08-23 17:16:59 -040026import android.os.RemoteException;
27import android.os.ServiceManager;
Jason Monk297c04e2018-08-23 17:16:59 -040028import android.service.notification.StatusBarNotification;
29import android.service.vr.IVrManager;
30import android.service.vr.IVrStateCallbacks;
Jason Monk297c04e2018-08-23 17:16:59 -040031import android.util.Log;
32import android.util.Slog;
Jason Monk297c04e2018-08-23 17:16:59 -040033import android.view.View;
34import android.view.ViewGroup;
35import android.view.accessibility.AccessibilityManager;
36import android.widget.TextView;
37
38import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
39import com.android.internal.statusbar.IStatusBarService;
Gus Prevasca1b6f72018-12-28 10:53:11 -050040import com.android.internal.statusbar.NotificationVisibility;
Selim Cinek9ba78f12018-12-07 14:37:33 -080041import com.android.internal.widget.MessagingGroup;
42import com.android.internal.widget.MessagingMessage;
Lucas Dupinc12fad32019-05-14 20:59:17 +000043import com.android.keyguard.KeyguardUpdateMonitor;
Jason Monk297c04e2018-08-23 17:16:59 -040044import com.android.systemui.Dependency;
Gus Prevaseb4e2e12018-12-28 14:57:59 -050045import com.android.systemui.ForegroundServiceNotificationListener;
Jason Monk297c04e2018-08-23 17:16:59 -040046import com.android.systemui.InitController;
47import com.android.systemui.R;
Jason Monk297c04e2018-08-23 17:16:59 -040048import com.android.systemui.plugins.ActivityStarter;
49import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
Beverly8fdb5332019-02-04 14:29:49 -050050import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jason Monk297c04e2018-08-23 17:16:59 -040051import com.android.systemui.statusbar.CommandQueue;
Heemin Seog98df6972019-12-05 13:01:38 -080052import com.android.systemui.statusbar.KeyguardIndicationController;
Jason Monk297c04e2018-08-23 17:16:59 -040053import com.android.systemui.statusbar.NotificationLockscreenUserManager;
54import com.android.systemui.statusbar.NotificationMediaManager;
55import com.android.systemui.statusbar.NotificationPresenter;
56import com.android.systemui.statusbar.NotificationRemoteInputManager;
Jason Monk297c04e2018-08-23 17:16:59 -040057import com.android.systemui.statusbar.NotificationViewHierarchyManager;
Jason Monk297c04e2018-08-23 17:16:59 -040058import com.android.systemui.statusbar.StatusBarState;
Beverly8fdb5332019-02-04 14:29:49 -050059import com.android.systemui.statusbar.SysuiStatusBarStateController;
Jason Monk297c04e2018-08-23 17:16:59 -040060import com.android.systemui.statusbar.notification.AboveShelfObserver;
61import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
Selim Cinek5454a0d2019-07-30 17:14:50 -070062import com.android.systemui.statusbar.notification.DynamicPrivacyController;
Gus Prevasb43dc652018-12-20 13:11:45 -050063import com.android.systemui.statusbar.notification.NotificationAlertingManager;
Gus Prevas26bc59b2018-12-19 11:26:39 -050064import com.android.systemui.statusbar.notification.NotificationEntryListener;
Jason Monk297c04e2018-08-23 17:16:59 -040065import com.android.systemui.statusbar.notification.NotificationEntryManager;
Gus Prevasec9e1f02018-12-18 15:28:12 -050066import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
Gus Prevas5b9098dc2018-12-21 17:07:15 -050067import com.android.systemui.statusbar.notification.VisualStabilityManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050068import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Ned Burnsc5864672019-02-20 12:57:29 -050069import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
Jason Monk297c04e2018-08-23 17:16:59 -040070import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
71import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
72import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
73import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
74import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
75import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
Selim Cinek9ba78f12018-12-07 14:37:33 -080076import com.android.systemui.statusbar.policy.ConfigurationController;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040077import com.android.systemui.statusbar.policy.KeyguardStateController;
Jason Monk297c04e2018-08-23 17:16:59 -040078
Evan Laird181de622019-10-24 09:53:02 -040079import java.util.List;
Selim Cinekab9c7b22018-12-11 18:15:47 -080080
Selim Cinek9ba78f12018-12-07 14:37:33 -080081public class StatusBarNotificationPresenter implements NotificationPresenter,
Ned Burnsc5864672019-02-20 12:57:29 -050082 ConfigurationController.ConfigurationListener,
Beverlyea2010c2019-11-04 09:55:29 -050083 NotificationRowBinderImpl.BindRowCallback,
84 CommandQueue.Callbacks {
Jason Monk297c04e2018-08-23 17:16:59 -040085
86 private final LockscreenGestureLogger mLockscreenGestureLogger =
87 Dependency.get(LockscreenGestureLogger.class);
88
89 private static final String TAG = "StatusBarNotificationPresenter";
90
Jason Monk297c04e2018-08-23 17:16:59 -040091 private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
Lucas Dupind236ee32019-10-08 15:33:59 -070092 private final KeyguardStateController mKeyguardStateController;
Jason Monk297c04e2018-08-23 17:16:59 -040093 private final NotificationViewHierarchyManager mViewHierarchyManager =
94 Dependency.get(NotificationViewHierarchyManager.class);
95 private final NotificationLockscreenUserManager mLockscreenUserManager =
96 Dependency.get(NotificationLockscreenUserManager.class);
Beverly8fdb5332019-02-04 14:29:49 -050097 private final SysuiStatusBarStateController mStatusBarStateController =
98 (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
Jason Monk297c04e2018-08-23 17:16:59 -040099 private final NotificationEntryManager mEntryManager =
100 Dependency.get(NotificationEntryManager.class);
Gus Prevasec9e1f02018-12-18 15:28:12 -0500101 private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
102 Dependency.get(NotificationInterruptionStateProvider.class);
Jason Monk297c04e2018-08-23 17:16:59 -0400103 private final NotificationMediaManager mMediaManager =
104 Dependency.get(NotificationMediaManager.class);
Gus Prevas5b9098dc2018-12-21 17:07:15 -0500105 private final VisualStabilityManager mVisualStabilityManager =
106 Dependency.get(VisualStabilityManager.class);
Ned Burns1016d962019-01-08 16:52:39 -0500107 private final NotificationGutsManager mGutsManager =
108 Dependency.get(NotificationGutsManager.class);
Jason Monk297c04e2018-08-23 17:16:59 -0400109
Dave Mankoff59b94962019-12-16 16:42:15 -0500110 private final NotificationPanelViewController mNotificationPanel;
Jason Monk297c04e2018-08-23 17:16:59 -0400111 private final HeadsUpManagerPhone mHeadsUpManager;
112 private final AboveShelfObserver mAboveShelfObserver;
113 private final DozeScrimController mDozeScrimController;
114 private final ScrimController mScrimController;
115 private final Context mContext;
Heemin Seog98df6972019-12-05 13:01:38 -0800116 private final KeyguardIndicationController mKeyguardIndicationController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800117 private final StatusBar mStatusBar;
Heemin Seogba6337f2019-12-10 15:34:37 -0800118 private final ShadeController mShadeController;
Jason Monk297c04e2018-08-23 17:16:59 -0400119 private final CommandQueue mCommandQueue;
120
121 private final AccessibilityManager mAccessibilityManager;
Jason Monk297c04e2018-08-23 17:16:59 -0400122 private final KeyguardManager mKeyguardManager;
123 private final ActivityLaunchAnimator mActivityLaunchAnimator;
124 private final int mMaxAllowedKeyguardNotifications;
125 private final IStatusBarService mBarService;
Selim Cinek5454a0d2019-07-30 17:14:50 -0700126 private final DynamicPrivacyController mDynamicPrivacyController;
Lucas Dupinc12fad32019-05-14 20:59:17 +0000127 private boolean mReinflateNotificationsOnUserSwitched;
128 private boolean mDispatchUiModeChangeOnUserSwitched;
Jason Monk297c04e2018-08-23 17:16:59 -0400129 private TextView mNotificationPanelDebugText;
130
131 protected boolean mVrMode;
132 private int mMaxKeyguardNotifications;
Jason Monk297c04e2018-08-23 17:16:59 -0400133
Gus Prevas21437b32018-12-05 10:36:13 -0500134 public StatusBarNotificationPresenter(Context context,
Dave Mankoff59b94962019-12-16 16:42:15 -0500135 NotificationPanelViewController panel,
Gus Prevas21437b32018-12-05 10:36:13 -0500136 HeadsUpManagerPhone headsUp,
137 StatusBarWindowView statusBarWindow,
138 ViewGroup stackScroller,
139 DozeScrimController dozeScrimController,
Jason Monk297c04e2018-08-23 17:16:59 -0400140 ScrimController scrimController,
Gus Prevas0b8174a2018-12-07 11:35:53 -0500141 ActivityLaunchAnimator activityLaunchAnimator,
Selim Cinek5454a0d2019-07-30 17:14:50 -0700142 DynamicPrivacyController dynamicPrivacyController,
Ned Burnsc5864672019-02-20 12:57:29 -0500143 NotificationAlertingManager notificationAlertingManager,
Lucas Dupind236ee32019-10-08 15:33:59 -0700144 NotificationRowBinderImpl notificationRowBinder,
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400145 KeyguardStateController keyguardStateController,
Heemin Seog98df6972019-12-05 13:01:38 -0800146 KeyguardIndicationController keyguardIndicationController,
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800147 StatusBar statusBar,
Heemin Seogba6337f2019-12-10 15:34:37 -0800148 ShadeController shadeController,
Dave Mankoff71fca1a2019-12-19 14:16:32 -0500149 CommandQueue commandQueue,
150 InitController initController) {
Jason Monk297c04e2018-08-23 17:16:59 -0400151 mContext = context;
Lucas Dupind236ee32019-10-08 15:33:59 -0700152 mKeyguardStateController = keyguardStateController;
Jason Monk297c04e2018-08-23 17:16:59 -0400153 mNotificationPanel = panel;
154 mHeadsUpManager = headsUp;
Selim Cinek5454a0d2019-07-30 17:14:50 -0700155 mDynamicPrivacyController = dynamicPrivacyController;
Heemin Seog98df6972019-12-05 13:01:38 -0800156 mKeyguardIndicationController = keyguardIndicationController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800157 // TODO: use KeyguardStateController#isOccluded to remove this dependency
158 mStatusBar = statusBar;
Heemin Seogba6337f2019-12-10 15:34:37 -0800159 mShadeController = shadeController;
Dave Mankoffbcaca8a2019-10-31 18:04:08 -0400160 mCommandQueue = commandQueue;
Jason Monk297c04e2018-08-23 17:16:59 -0400161 mAboveShelfObserver = new AboveShelfObserver(stackScroller);
Gus Prevas21437b32018-12-05 10:36:13 -0500162 mActivityLaunchAnimator = activityLaunchAnimator;
Jason Monk297c04e2018-08-23 17:16:59 -0400163 mAboveShelfObserver.setListener(statusBarWindow.findViewById(
164 R.id.notification_container_parent));
165 mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
166 mDozeScrimController = dozeScrimController;
167 mScrimController = scrimController;
Jason Monk297c04e2018-08-23 17:16:59 -0400168 mKeyguardManager = context.getSystemService(KeyguardManager.class);
169 mMaxAllowedKeyguardNotifications = context.getResources().getInteger(
170 R.integer.keyguard_max_notification_count);
171 mBarService = IStatusBarService.Stub.asInterface(
172 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Jason Monk297c04e2018-08-23 17:16:59 -0400173
174 if (MULTIUSER_DEBUG) {
Dave Mankoff59b94962019-12-16 16:42:15 -0500175 mNotificationPanelDebugText = mNotificationPanel.getHeaderDebugInfo();
Jason Monk297c04e2018-08-23 17:16:59 -0400176 mNotificationPanelDebugText.setVisibility(View.VISIBLE);
177 }
178
179 IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
180 Context.VR_SERVICE));
181 if (vrManager != null) {
182 try {
183 vrManager.registerListener(mVrStateCallbacks);
184 } catch (RemoteException e) {
185 Slog.e(TAG, "Failed to register VR mode state listener: " + e);
186 }
187 }
Gus Prevas21437b32018-12-05 10:36:13 -0500188 NotificationRemoteInputManager remoteInputManager =
189 Dependency.get(NotificationRemoteInputManager.class);
190 remoteInputManager.setUpWithCallback(
Jason Monk297c04e2018-08-23 17:16:59 -0400191 Dependency.get(NotificationRemoteInputManager.Callback.class),
192 mNotificationPanel.createRemoteInputDelegate());
Gus Prevas21437b32018-12-05 10:36:13 -0500193 remoteInputManager.getController().addCallback(
Jason Monk297c04e2018-08-23 17:16:59 -0400194 Dependency.get(StatusBarWindowController.class));
195
196 NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
Dave Mankoff71fca1a2019-12-19 14:16:32 -0500197 initController.addPostInitTask(() -> {
Gus Prevas26bc59b2018-12-19 11:26:39 -0500198 NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
199 @Override
Gus Prevas772e5322018-12-21 16:22:16 -0500200 public void onEntryRemoved(
Ned Burnsf81c4c42019-01-07 14:10:43 -0500201 @Nullable NotificationEntry entry,
Gus Prevasca1b6f72018-12-28 10:53:11 -0500202 NotificationVisibility visibility,
Gus Prevas772e5322018-12-21 16:22:16 -0500203 boolean removedByUser) {
Ned Burnsef2ef6c2019-01-02 16:48:08 -0500204 StatusBarNotificationPresenter.this.onNotificationRemoved(
Ned Burns00b4b2d2019-10-17 22:09:27 -0400205 entry.getKey(), entry.getSbn());
Gus Prevasdca2be52018-12-21 11:25:10 -0500206 if (removedByUser) {
207 maybeEndAmbientPulse();
208 }
Gus Prevas26bc59b2018-12-19 11:26:39 -0500209 }
210 };
211
Jason Monk297c04e2018-08-23 17:16:59 -0400212 mViewHierarchyManager.setUpWithPresenter(this, notifListContainer);
Gus Prevas8621bd22018-12-20 15:04:25 -0500213 mEntryManager.setUpWithPresenter(this, notifListContainer, mHeadsUpManager);
214 mEntryManager.addNotificationEntryListener(notificationEntryListener);
Gus Prevas5c84abb2018-12-28 16:41:49 -0500215 mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
Ned Burns1016d962019-01-08 16:52:39 -0500216 mEntryManager.addNotificationLifetimeExtender(mGutsManager);
Gus Prevas5c84abb2018-12-28 16:41:49 -0500217 mEntryManager.addNotificationLifetimeExtenders(
218 remoteInputManager.getLifetimeExtenders());
Ned Burnsc5864672019-02-20 12:57:29 -0500219 notificationRowBinder.setUpWithPresenter(this, notifListContainer, mHeadsUpManager,
Gus Prevas8ba88a82018-12-18 11:13:44 -0500220 mEntryManager, this);
Gus Prevasec9e1f02018-12-18 15:28:12 -0500221 mNotificationInterruptionStateProvider.setUpWithPresenter(
222 this, mHeadsUpManager, this::canHeadsUp);
Jason Monk297c04e2018-08-23 17:16:59 -0400223 mLockscreenUserManager.setUpWithPresenter(this);
224 mMediaManager.setUpWithPresenter(this);
Gus Prevas5b9098dc2018-12-21 17:07:15 -0500225 mVisualStabilityManager.setUpWithPresenter(this);
Ned Burns1016d962019-01-08 16:52:39 -0500226 mGutsManager.setUpWithPresenter(this,
Jason Monk297c04e2018-08-23 17:16:59 -0400227 notifListContainer, mCheckSaveListener, mOnSettingsClickListener);
Evan Laird3ceaa9b2019-08-05 17:11:54 -0400228 // ForegroundServiceNotificationListener adds its listener in its constructor
Gus Prevaseb4e2e12018-12-28 14:57:59 -0500229 // but we need to request it here in order for it to be instantiated.
230 // TODO: figure out how to do this correctly once Dependency.get() is gone.
231 Dependency.get(ForegroundServiceNotificationListener.class);
Jason Monk297c04e2018-08-23 17:16:59 -0400232
233 onUserSwitched(mLockscreenUserManager.getCurrentUserId());
234 });
Selim Cinek9ba78f12018-12-07 14:37:33 -0800235 Dependency.get(ConfigurationController.class).addCallback(this);
Gus Prevasb43dc652018-12-20 13:11:45 -0500236
237 notificationAlertingManager.setHeadsUpManager(mHeadsUpManager);
Jason Monk297c04e2018-08-23 17:16:59 -0400238 }
239
Selim Cinek9ba78f12018-12-07 14:37:33 -0800240 @Override
Jason Monk297c04e2018-08-23 17:16:59 -0400241 public void onDensityOrFontScaleChanged() {
Selim Cinek9ba78f12018-12-07 14:37:33 -0800242 MessagingMessage.dropCache();
243 MessagingGroup.dropCache();
Dave Mankoffe2294692019-08-14 11:53:13 -0400244 if (!Dependency.get(KeyguardUpdateMonitor.class).isSwitchingUser()) {
Lucas Dupinc12fad32019-05-14 20:59:17 +0000245 updateNotificationsOnDensityOrFontScaleChanged();
246 } else {
247 mReinflateNotificationsOnUserSwitched = true;
248 }
Jason Monk297c04e2018-08-23 17:16:59 -0400249 }
250
251 @Override
Selim Cinekab9c7b22018-12-11 18:15:47 -0800252 public void onUiModeChanged() {
Dave Mankoffe2294692019-08-14 11:53:13 -0400253 if (!Dependency.get(KeyguardUpdateMonitor.class).isSwitchingUser()) {
Lucas Dupinc12fad32019-05-14 20:59:17 +0000254 updateNotificationOnUiModeChanged();
255 } else {
256 mDispatchUiModeChangeOnUserSwitched = true;
257 }
Selim Cinekab9c7b22018-12-11 18:15:47 -0800258 }
259
Selim Cinekdd26a7e2019-02-11 18:42:55 -0800260 @Override
261 public void onOverlayChanged() {
262 onDensityOrFontScaleChanged();
263 }
264
Selim Cinekab9c7b22018-12-11 18:15:47 -0800265 private void updateNotificationOnUiModeChanged() {
Evan Laird181de622019-10-24 09:53:02 -0400266 List<NotificationEntry> userNotifications =
267 mEntryManager.getActiveNotificationsForCurrentUser();
Selim Cinekab9c7b22018-12-11 18:15:47 -0800268 for (int i = 0; i < userNotifications.size(); i++) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500269 NotificationEntry entry = userNotifications.get(i);
Selim Cinekab9c7b22018-12-11 18:15:47 -0800270 ExpandableNotificationRow row = entry.getRow();
271 if (row != null) {
272 row.onUiModeChanged();
273 }
274 }
275 }
276
Ned Burns1016d962019-01-08 16:52:39 -0500277 private void updateNotificationsOnDensityOrFontScaleChanged() {
Evan Laird181de622019-10-24 09:53:02 -0400278 List<NotificationEntry> userNotifications =
279 mEntryManager.getActiveNotificationsForCurrentUser();
Ned Burns1016d962019-01-08 16:52:39 -0500280 for (int i = 0; i < userNotifications.size(); i++) {
281 NotificationEntry entry = userNotifications.get(i);
282 entry.onDensityOrFontScaleChanged();
283 boolean exposedGuts = entry.areGutsExposed();
284 if (exposedGuts) {
285 mGutsManager.onDensityOrFontScaleChanged(entry);
286 }
287 }
288 }
289
Selim Cinekab9c7b22018-12-11 18:15:47 -0800290 @Override
Jason Monk297c04e2018-08-23 17:16:59 -0400291 public boolean isCollapsing() {
292 return mNotificationPanel.isCollapsing()
293 || mActivityLaunchAnimator.isAnimationPending()
294 || mActivityLaunchAnimator.isAnimationRunning();
295 }
296
Gus Prevasdca2be52018-12-21 11:25:10 -0500297 private void maybeEndAmbientPulse() {
Jason Monk297c04e2018-08-23 17:16:59 -0400298 if (mNotificationPanel.hasPulsingNotifications() &&
Selim Cinekc3fec682019-06-06 18:11:07 -0700299 !mHeadsUpManager.hasNotifications()) {
Jason Monk297c04e2018-08-23 17:16:59 -0400300 // We were showing a pulse for a notification, but no notifications are pulsing anymore.
301 // Finish the pulse.
302 mDozeScrimController.pulseOutNow();
303 }
304 }
305
306 @Override
307 public void updateNotificationViews() {
308 // The function updateRowStates depends on both of these being non-null, so check them here.
309 // We may be called before they are set from DeviceProvisionedController's callback.
310 if (mScrimController == null) return;
311
312 // Do not modify the notifications during collapse.
313 if (isCollapsing()) {
314 mShadeController.addPostCollapseAction(this::updateNotificationViews);
315 return;
316 }
317
318 mViewHierarchyManager.updateNotificationViews();
319
320 mNotificationPanel.updateNotificationViews();
321 }
322
Jason Monk297c04e2018-08-23 17:16:59 -0400323 public void onNotificationRemoved(String key, StatusBarNotification old) {
324 if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
325
326 if (old != null) {
327 if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
328 && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
329 if (mStatusBarStateController.getState() == StatusBarState.SHADE) {
330 mCommandQueue.animateCollapsePanels();
331 } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
332 && !isCollapsing()) {
Heemin Seog98df6972019-12-05 13:01:38 -0800333 mStatusBarStateController.setState(StatusBarState.KEYGUARD);
Jason Monk297c04e2018-08-23 17:16:59 -0400334 }
335 }
336 }
Jason Monk297c04e2018-08-23 17:16:59 -0400337 }
338
339 public boolean hasActiveNotifications() {
Evan Laird181de622019-10-24 09:53:02 -0400340 return mEntryManager.hasActiveNotifications();
Jason Monk297c04e2018-08-23 17:16:59 -0400341 }
342
Ned Burnsf81c4c42019-01-07 14:10:43 -0500343 public boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn) {
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800344 if (mStatusBar.isOccluded()) {
Jason Monk297c04e2018-08-23 17:16:59 -0400345 boolean devicePublic = mLockscreenUserManager.
346 isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
347 boolean userPublic = devicePublic
348 || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
349 boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
350 if (userPublic && needsRedaction) {
Selim Cinekc3fec682019-06-06 18:11:07 -0700351 // TODO(b/135046837): we can probably relax this with dynamic privacy
Jason Monk297c04e2018-08-23 17:16:59 -0400352 return false;
353 }
354 }
355
356 if (!mCommandQueue.panelsEnabled()) {
357 if (DEBUG) {
358 Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
359 }
360 return false;
361 }
362
363 if (sbn.getNotification().fullScreenIntent != null) {
364 if (mAccessibilityManager.isTouchExplorationEnabled()) {
365 if (DEBUG) Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
366 return false;
367 } else {
368 // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400369 return !mKeyguardStateController.isShowing()
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800370 || mStatusBar.isOccluded();
Jason Monk297c04e2018-08-23 17:16:59 -0400371 }
372 }
373 return true;
374 }
375
376 @Override
377 public void onUserSwitched(int newUserId) {
378 // Begin old BaseStatusBar.userSwitched
379 mHeadsUpManager.setUser(newUserId);
380 // End old BaseStatusBar.userSwitched
381 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
382 mCommandQueue.animateCollapsePanels();
Lucas Dupinc12fad32019-05-14 20:59:17 +0000383 if (mReinflateNotificationsOnUserSwitched) {
384 updateNotificationsOnDensityOrFontScaleChanged();
385 mReinflateNotificationsOnUserSwitched = false;
386 }
387 if (mDispatchUiModeChangeOnUserSwitched) {
388 updateNotificationOnUiModeChanged();
389 mDispatchUiModeChangeOnUserSwitched = false;
390 }
Jason Monk297c04e2018-08-23 17:16:59 -0400391 updateNotificationViews();
392 mMediaManager.clearCurrentMediaNotification();
Heemin Seogba6337f2019-12-10 15:34:37 -0800393 mStatusBar.setLockscreenUser(newUserId);
Jason Monk297c04e2018-08-23 17:16:59 -0400394 updateMediaMetaData(true, false);
395 }
396
397 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500398 public void onBindRow(NotificationEntry entry, PackageManager pmUser,
Jason Monk297c04e2018-08-23 17:16:59 -0400399 StatusBarNotification sbn, ExpandableNotificationRow row) {
400 row.setAboveShelfChangedListener(mAboveShelfObserver);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400401 row.setSecureStateProvider(mKeyguardStateController::canDismissLockScreen);
Jason Monk297c04e2018-08-23 17:16:59 -0400402 }
403
404 @Override
405 public boolean isPresenterFullyCollapsed() {
406 return mNotificationPanel.isFullyCollapsed();
407 }
408
409 @Override
410 public void onActivated(ActivatableNotificationView view) {
411 onActivated();
412 if (view != null) mNotificationPanel.setActivatedChild(view);
413 }
414
415 public void onActivated() {
416 mLockscreenGestureLogger.write(
417 MetricsEvent.ACTION_LS_NOTE,
418 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
419 mNotificationPanel.showTransientIndication(R.string.notification_tap_again);
420 ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
421 if (previousView != null) {
422 previousView.makeInactive(true /* animate */);
423 }
424 }
425
426 @Override
427 public void onActivationReset(ActivatableNotificationView view) {
428 if (view == mNotificationPanel.getActivatedChild()) {
429 mNotificationPanel.setActivatedChild(null);
Heemin Seog98df6972019-12-05 13:01:38 -0800430 mKeyguardIndicationController.hideTransientIndication();
Jason Monk297c04e2018-08-23 17:16:59 -0400431 }
432 }
433
434 @Override
435 public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
436 mMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation);
437 }
438
439 @Override
Jason Monk297c04e2018-08-23 17:16:59 -0400440 public int getMaxNotificationsWhileLocked(boolean recompute) {
441 if (recompute) {
442 mMaxKeyguardNotifications = Math.max(1,
443 mNotificationPanel.computeMaxKeyguardNotifications(
444 mMaxAllowedKeyguardNotifications));
445 return mMaxKeyguardNotifications;
446 }
447 return mMaxKeyguardNotifications;
448 }
449
450 @Override
451 public void onUpdateRowStates() {
452 mNotificationPanel.onUpdateRowStates();
453 }
454
455 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500456 public void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded) {
Jason Monk297c04e2018-08-23 17:16:59 -0400457 mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
Selim Cinek5454a0d2019-07-30 17:14:50 -0700458 if (nowExpanded) {
459 if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
460 mShadeController.goToLockedShade(clickedEntry.getRow());
461 } else if (clickedEntry.isSensitive()
462 && mDynamicPrivacyController.isInLockedDownShade()) {
463 mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
464 mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
465 , null /* cancelRunnable */, false /* afterKeyguardGone */);
466 }
Jason Monk297c04e2018-08-23 17:16:59 -0400467 }
468 }
469
470 @Override
471 public boolean isDeviceInVrMode() {
472 return mVrMode;
473 }
474
Jason Monk297c04e2018-08-23 17:16:59 -0400475 private void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
476 mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
477 mActivityStarter.dismissKeyguardThenExecute(dismissAction, null,
478 true /* afterKeyguardGone */);
479 }
480
Jason Monk297c04e2018-08-23 17:16:59 -0400481 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
482 @Override
483 public void onVrStateChanged(boolean enabled) {
484 mVrMode = enabled;
485 }
486 };
487
488 private final CheckSaveListener mCheckSaveListener = new CheckSaveListener() {
489 @Override
490 public void checkSave(Runnable saveImportance, StatusBarNotification sbn) {
Jason Monk297c04e2018-08-23 17:16:59 -0400491 // If the user has security enabled, show challenge if the setting is changed.
492 if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
493 && mKeyguardManager.isKeyguardLocked()) {
494 onLockedNotificationImportanceChange(() -> {
495 saveImportance.run();
496 return true;
497 });
498 } else {
499 saveImportance.run();
500 }
501 }
502 };
503
504 private final OnSettingsClickListener mOnSettingsClickListener = new OnSettingsClickListener() {
505 @Override
506 public void onSettingsClick(String key) {
507 try {
508 mBarService.onNotificationSettingsViewed(key);
509 } catch (RemoteException e) {
510 // if we're here we're dead
511 }
512 }
513 };
514}