blob: 0f3b5db2d281d2bbc410d8ed876435e743e27ce1 [file] [log] [blame]
Gus Prevas21437b32018-12-05 10:36:13 -05001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.phone;
18
Mady Mellorc2ff0112019-03-28 14:18:06 -070019import static android.service.notification.NotificationListenerService.REASON_CLICK;
20
Gus Prevas21437b32018-12-05 10:36:13 -050021import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
22
23import android.app.ActivityManager;
24import android.app.ActivityTaskManager;
25import android.app.KeyguardManager;
26import android.app.Notification;
Gus Prevasd65c2db2018-12-18 17:13:38 -050027import android.app.NotificationManager;
Gus Prevas21437b32018-12-05 10:36:13 -050028import android.app.PendingIntent;
29import android.app.TaskStackBuilder;
30import android.content.Context;
31import android.content.Intent;
32import android.os.AsyncTask;
Mark Renouf6b2331c2019-03-21 13:40:08 -040033import android.os.Handler;
Gus Prevas21437b32018-12-05 10:36:13 -050034import android.os.Looper;
35import android.os.RemoteException;
Gus Prevas21437b32018-12-05 10:36:13 -050036import android.os.UserHandle;
Gus Prevasd65c2db2018-12-18 17:13:38 -050037import android.service.dreams.IDreamManager;
Gus Prevas21437b32018-12-05 10:36:13 -050038import android.service.notification.StatusBarNotification;
39import android.text.TextUtils;
Gus Prevasd65c2db2018-12-18 17:13:38 -050040import android.util.EventLog;
Gus Prevas21437b32018-12-05 10:36:13 -050041import android.util.Log;
42import android.view.RemoteAnimationAdapter;
Evan Laird2ec752d2019-11-13 19:03:46 -050043import android.view.View;
Gus Prevas21437b32018-12-05 10:36:13 -050044
Gus Prevasd65c2db2018-12-18 17:13:38 -050045import com.android.internal.logging.MetricsLogger;
Gus Prevas21437b32018-12-05 10:36:13 -050046import com.android.internal.statusbar.IStatusBarService;
47import com.android.internal.statusbar.NotificationVisibility;
48import com.android.internal.widget.LockPatternUtils;
Mark Renouf6b2331c2019-03-21 13:40:08 -040049import com.android.systemui.ActivityIntentHelper;
Gus Prevasd65c2db2018-12-18 17:13:38 -050050import com.android.systemui.EventLogTags;
Gus Prevas21437b32018-12-05 10:36:13 -050051import com.android.systemui.assist.AssistManager;
Mark Renouffec45da2019-03-13 13:24:27 -040052import com.android.systemui.bubbles.BubbleController;
Dave Mankoff00e8a2f2019-12-18 16:59:49 -050053import com.android.systemui.dagger.qualifiers.Background;
54import com.android.systemui.dagger.qualifiers.Main;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -050055import com.android.systemui.dagger.qualifiers.UiBackground;
Gus Prevas21437b32018-12-05 10:36:13 -050056import com.android.systemui.plugins.ActivityStarter;
Beverly8fdb5332019-02-04 14:29:49 -050057import com.android.systemui.plugins.statusbar.StatusBarStateController;
Gus Prevas21437b32018-12-05 10:36:13 -050058import com.android.systemui.statusbar.CommandQueue;
59import com.android.systemui.statusbar.NotificationLockscreenUserManager;
60import com.android.systemui.statusbar.NotificationPresenter;
61import com.android.systemui.statusbar.NotificationRemoteInputManager;
62import com.android.systemui.statusbar.RemoteInputController;
63import com.android.systemui.statusbar.StatusBarState;
Gus Prevas21437b32018-12-05 10:36:13 -050064import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
65import com.android.systemui.statusbar.notification.NotificationActivityStarter;
Gus Prevasd65c2db2018-12-18 17:13:38 -050066import com.android.systemui.statusbar.notification.NotificationEntryListener;
Gus Prevas21437b32018-12-05 10:36:13 -050067import com.android.systemui.statusbar.notification.NotificationEntryManager;
Gus Prevasd65c2db2018-12-18 17:13:38 -050068import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
Ned Burnsf81c4c42019-01-07 14:10:43 -050069import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gustav Senntonf892fe92019-01-22 15:31:42 +000070import com.android.systemui.statusbar.notification.logging.NotificationLogger;
Gus Prevas21437b32018-12-05 10:36:13 -050071import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
72import com.android.systemui.statusbar.policy.HeadsUpUtil;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040073import com.android.systemui.statusbar.policy.KeyguardStateController;
Gus Prevas21437b32018-12-05 10:36:13 -050074
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -050075import java.util.concurrent.Executor;
76
Dave Mankoff4c73e652019-11-14 17:39:08 -050077import javax.inject.Inject;
78import javax.inject.Singleton;
79
80import dagger.Lazy;
81
Gus Prevas21437b32018-12-05 10:36:13 -050082/**
83 * Status bar implementation of {@link NotificationActivityStarter}.
84 */
85public class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
86
Evan Laird2ec752d2019-11-13 19:03:46 -050087 private static final String TAG = "NotifActivityStarter";
Gus Prevasd65c2db2018-12-18 17:13:38 -050088 protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Gus Prevas21437b32018-12-05 10:36:13 -050089
Dave Mankoff4c73e652019-11-14 17:39:08 -050090 private final Lazy<AssistManager> mAssistManagerLazy;
Mark Renouf906a93f2019-03-15 16:04:58 -040091 private final NotificationGroupManager mGroupManager;
92 private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
93 private final NotificationRemoteInputManager mRemoteInputManager;
94 private final NotificationLockscreenUserManager mLockscreenUserManager;
95 private final ShadeController mShadeController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -080096 private final StatusBar mStatusBar;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040097 private final KeyguardStateController mKeyguardStateController;
Mark Renouf906a93f2019-03-15 16:04:58 -040098 private final ActivityStarter mActivityStarter;
99 private final NotificationEntryManager mEntryManager;
100 private final StatusBarStateController mStatusBarStateController;
101 private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
102 private final MetricsLogger mMetricsLogger;
Gus Prevas21437b32018-12-05 10:36:13 -0500103 private final Context mContext;
Dave Mankoff59b94962019-12-16 16:42:15 -0500104 private final NotificationPanelViewController mNotificationPanel;
Gus Prevas21437b32018-12-05 10:36:13 -0500105 private final NotificationPresenter mPresenter;
106 private final LockPatternUtils mLockPatternUtils;
107 private final HeadsUpManagerPhone mHeadsUpManager;
Heemin Seog98df6972019-12-05 13:01:38 -0800108 private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Gus Prevas21437b32018-12-05 10:36:13 -0500109 private final KeyguardManager mKeyguardManager;
110 private final ActivityLaunchAnimator mActivityLaunchAnimator;
111 private final IStatusBarService mBarService;
112 private final CommandQueue mCommandQueue;
Gus Prevasd65c2db2018-12-18 17:13:38 -0500113 private final IDreamManager mDreamManager;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400114 private final Handler mMainThreadHandler;
Mark Renouffec45da2019-03-13 13:24:27 -0400115 private final Handler mBackgroundHandler;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400116 private final ActivityIntentHelper mActivityIntentHelper;
Mark Renouffec45da2019-03-13 13:24:27 -0400117 private final BubbleController mBubbleController;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500118 private final Executor mUiBgExecutor;
Gus Prevas21437b32018-12-05 10:36:13 -0500119
120 private boolean mIsCollapsingToShowActivityOverLockscreen;
121
Dave Mankoff4c73e652019-11-14 17:39:08 -0500122 private StatusBarNotificationActivityStarter(Context context, CommandQueue commandQueue,
Dave Mankoff59b94962019-12-16 16:42:15 -0500123 Lazy<AssistManager> assistManagerLazy, NotificationPanelViewController panel,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500124 NotificationPresenter presenter, NotificationEntryManager entryManager,
125 HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter,
126 ActivityLaunchAnimator activityLaunchAnimator, IStatusBarService statusBarService,
Heemin Seog98df6972019-12-05 13:01:38 -0800127 StatusBarStateController statusBarStateController,
128 StatusBarKeyguardViewManager statusBarKeyguardViewManager,
129 KeyguardManager keyguardManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500130 IDreamManager dreamManager, NotificationRemoteInputManager remoteInputManager,
131 StatusBarRemoteInputCallback remoteInputCallback, NotificationGroupManager groupManager,
Mark Renouf906a93f2019-03-15 16:04:58 -0400132 NotificationLockscreenUserManager lockscreenUserManager,
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800133 ShadeController shadeController, StatusBar statusBar,
134 KeyguardStateController keyguardStateController,
Mark Renouf906a93f2019-03-15 16:04:58 -0400135 NotificationInterruptionStateProvider notificationInterruptionStateProvider,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500136 MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500137 Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500138 ActivityIntentHelper activityIntentHelper, BubbleController bubbleController) {
Gus Prevas21437b32018-12-05 10:36:13 -0500139 mContext = context;
140 mNotificationPanel = panel;
141 mPresenter = presenter;
Gus Prevas21437b32018-12-05 10:36:13 -0500142 mHeadsUpManager = headsUpManager;
Gus Prevas21437b32018-12-05 10:36:13 -0500143 mActivityLaunchAnimator = activityLaunchAnimator;
Mark Renouf906a93f2019-03-15 16:04:58 -0400144 mBarService = statusBarService;
145 mCommandQueue = commandQueue;
Heemin Seog98df6972019-12-05 13:01:38 -0800146 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
Mark Renouf906a93f2019-03-15 16:04:58 -0400147 mKeyguardManager = keyguardManager;
148 mDreamManager = dreamManager;
149 mRemoteInputManager = remoteInputManager;
150 mLockscreenUserManager = lockscreenUserManager;
151 mShadeController = shadeController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800152 // TODO: use KeyguardStateController#isOccluded to remove this dependency
153 mStatusBar = statusBar;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400154 mKeyguardStateController = keyguardStateController;
Mark Renouf906a93f2019-03-15 16:04:58 -0400155 mActivityStarter = activityStarter;
156 mEntryManager = entryManager;
157 mStatusBarStateController = statusBarStateController;
158 mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
159 mMetricsLogger = metricsLogger;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500160 mAssistManagerLazy = assistManagerLazy;
Mark Renouf906a93f2019-03-15 16:04:58 -0400161 mGroupManager = groupManager;
162 mLockPatternUtils = lockPatternUtils;
Mark Renouffec45da2019-03-13 13:24:27 -0400163 mBackgroundHandler = backgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500164 mUiBgExecutor = uiBgExecutor;
Gus Prevasd65c2db2018-12-18 17:13:38 -0500165 mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
166 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500167 public void onPendingEntryAdded(NotificationEntry entry) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500168 handleFullScreenIntent(entry);
169 }
170 });
Mark Renouf906a93f2019-03-15 16:04:58 -0400171 mStatusBarRemoteInputCallback = remoteInputCallback;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400172 mMainThreadHandler = mainThreadHandler;
173 mActivityIntentHelper = activityIntentHelper;
Mark Renouffec45da2019-03-13 13:24:27 -0400174 mBubbleController = bubbleController;
Gus Prevas21437b32018-12-05 10:36:13 -0500175 }
176
177 /**
178 * Called when a notification is clicked.
179 *
180 * @param sbn notification that was clicked
181 * @param row row for that notification
182 */
183 @Override
184 public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
185 RemoteInputController controller = mRemoteInputManager.getController();
186 if (controller.isRemoteInputActive(row.getEntry())
187 && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
188 // We have an active remote input typed and the user clicked on the notification.
189 // this was probably unintentional, so we're closing the edit text instead.
190 controller.closeRemoteInputs();
191 return;
192 }
193 Notification notification = sbn.getNotification();
194 final PendingIntent intent = notification.contentIntent != null
195 ? notification.contentIntent
196 : notification.fullScreenIntent;
Mark Renouffec45da2019-03-13 13:24:27 -0400197 final boolean isBubble = row.getEntry().isBubble();
198
199 // This code path is now executed for notification without a contentIntent.
200 // The only valid case is Bubble notifications. Guard against other cases
201 // entering here.
202 if (intent == null && !isBubble) {
203 Log.e(TAG, "onNotificationClicked called for non-clickable notification!");
204 return;
205 }
206
Mark Renouffec45da2019-03-13 13:24:27 -0400207 boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
Gus Prevas21437b32018-12-05 10:36:13 -0500208 final boolean afterKeyguardGone = isActivityIntent
Mark Renouf6b2331c2019-03-21 13:40:08 -0400209 && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
Gus Prevas21437b32018-12-05 10:36:13 -0500210 mLockscreenUserManager.getCurrentUserId());
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800211 final boolean wasOccluded = mStatusBar.isOccluded();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400212 boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
Mark Renouf6b2331c2019-03-21 13:40:08 -0400213 && mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
Gus Prevas21437b32018-12-05 10:36:13 -0500214 mLockscreenUserManager.getCurrentUserId());
215 ActivityStarter.OnDismissAction postKeyguardAction =
216 () -> handleNotificationClickAfterKeyguardDismissed(
Evan Laird2ec752d2019-11-13 19:03:46 -0500217 sbn, row, controller, intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500218 isActivityIntent, wasOccluded, showOverLockscreen);
219 if (showOverLockscreen) {
220 mIsCollapsingToShowActivityOverLockscreen = true;
221 postKeyguardAction.onDismiss();
222 } else {
223 mActivityStarter.dismissKeyguardThenExecute(
224 postKeyguardAction, null /* cancel */, afterKeyguardGone);
225 }
226 }
227
228 private boolean handleNotificationClickAfterKeyguardDismissed(
229 StatusBarNotification sbn,
230 ExpandableNotificationRow row,
231 RemoteInputController controller,
232 PendingIntent intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500233 boolean isActivityIntent,
234 boolean wasOccluded,
235 boolean showOverLockscreen) {
236 // TODO: Some of this code may be able to move to NotificationEntryManager.
Evan Laird2ec752d2019-11-13 19:03:46 -0500237 if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(sbn.getKey())) {
Gus Prevas21437b32018-12-05 10:36:13 -0500238 // Release the HUN notification to the shade.
239
240 if (mPresenter.isPresenterFullyCollapsed()) {
241 HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
242 }
243 //
244 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
245 // become canceled shortly by NoMan, but we can't assume that.
246 mHeadsUpManager.removeNotification(sbn.getKey(),
247 true /* releaseImmediately */);
248 }
249 StatusBarNotification parentToCancel = null;
250 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
251 StatusBarNotification summarySbn =
Ned Burns00b4b2d2019-10-17 22:09:27 -0400252 mGroupManager.getLogicalGroupSummary(sbn).getSbn();
Gus Prevas21437b32018-12-05 10:36:13 -0500253 if (shouldAutoCancel(summarySbn)) {
254 parentToCancel = summarySbn;
255 }
256 }
257 final StatusBarNotification parentToCancelFinal = parentToCancel;
258 final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
Evan Laird2ec752d2019-11-13 19:03:46 -0500259 sbn, row, controller, intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500260 isActivityIntent, wasOccluded, parentToCancelFinal);
261
262 if (showOverLockscreen) {
263 mShadeController.addPostCollapseAction(runnable);
264 mShadeController.collapsePanel(true /* animate */);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400265 } else if (mKeyguardStateController.isShowing()
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800266 && mStatusBar.isOccluded()) {
Heemin Seog98df6972019-12-05 13:01:38 -0800267 mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
Gus Prevas21437b32018-12-05 10:36:13 -0500268 mShadeController.collapsePanel();
269 } else {
Mark Renouffec45da2019-03-13 13:24:27 -0400270 mBackgroundHandler.postAtFrontOfQueue(runnable);
Gus Prevas21437b32018-12-05 10:36:13 -0500271 }
Gus Prevas21437b32018-12-05 10:36:13 -0500272 return !mNotificationPanel.isFullyCollapsed();
273 }
274
275 private void handleNotificationClickAfterPanelCollapsed(
276 StatusBarNotification sbn,
277 ExpandableNotificationRow row,
278 RemoteInputController controller,
279 PendingIntent intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500280 boolean isActivityIntent,
281 boolean wasOccluded,
282 StatusBarNotification parentToCancelFinal) {
Evan Laird2ec752d2019-11-13 19:03:46 -0500283 String notificationKey = sbn.getKey();
Gus Prevas21437b32018-12-05 10:36:13 -0500284 try {
285 // The intent we are sending is for the application, which
286 // won't have permission to immediately start an activity after
287 // the user switches to home. We know it is safe to do at this
288 // point, so make sure new activity switches are now allowed.
289 ActivityManager.getService().resumeAppSwitches();
290 } catch (RemoteException e) {
291 }
Gus Prevas21437b32018-12-05 10:36:13 -0500292 // If we are launching a work activity and require to launch
293 // separate work challenge, we defer the activity action and cancel
294 // notification until work challenge is unlocked.
295 if (isActivityIntent) {
296 final int userId = intent.getCreatorUserHandle().getIdentifier();
297 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
298 && mKeyguardManager.isDeviceLocked(userId)) {
299 // TODO(b/28935539): should allow certain activities to
300 // bypass work challenge
301 if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
302 intent.getIntentSender(), notificationKey)) {
303 // Show work challenge, do not run PendingIntent and
304 // remove notification
305 collapseOnMainThread();
306 return;
307 }
308 }
309 }
310 Intent fillInIntent = null;
Ned Burnsf81c4c42019-01-07 14:10:43 -0500311 NotificationEntry entry = row.getEntry();
Mark Renouffec45da2019-03-13 13:24:27 -0400312 final boolean isBubble = entry.isBubble();
Gus Prevas21437b32018-12-05 10:36:13 -0500313 CharSequence remoteInputText = null;
314 if (!TextUtils.isEmpty(entry.remoteInputText)) {
315 remoteInputText = entry.remoteInputText;
316 }
Evan Laird2ec752d2019-11-13 19:03:46 -0500317 if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(notificationKey)) {
Gus Prevas21437b32018-12-05 10:36:13 -0500318 fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
319 remoteInputText.toString());
320 }
Mark Renouffec45da2019-03-13 13:24:27 -0400321 if (isBubble) {
322 expandBubbleStackOnMainThread(notificationKey);
323 } else {
324 startNotificationIntent(intent, fillInIntent, row, wasOccluded, isActivityIntent);
325 }
326 if (isActivityIntent || isBubble) {
Dave Mankoff4c73e652019-11-14 17:39:08 -0500327 mAssistManagerLazy.get().hideAssist();
Gus Prevas21437b32018-12-05 10:36:13 -0500328 }
329 if (shouldCollapse()) {
330 collapseOnMainThread();
331 }
332
Evan Laird181de622019-10-24 09:53:02 -0400333 final int count = mEntryManager.getActiveNotificationsCount();
Evan Laird2ec752d2019-11-13 19:03:46 -0500334 final int rank = entry.getRanking().getRank();
Gustav Senntonf892fe92019-01-22 15:31:42 +0000335 NotificationVisibility.NotificationLocation location =
Evan Laird2ec752d2019-11-13 19:03:46 -0500336 NotificationLogger.getNotificationLocation(entry);
Gus Prevas21437b32018-12-05 10:36:13 -0500337 final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
Gustav Senntonf892fe92019-01-22 15:31:42 +0000338 rank, count, true, location);
Gus Prevas21437b32018-12-05 10:36:13 -0500339 try {
340 mBarService.onNotificationClick(notificationKey, nv);
341 } catch (RemoteException ex) {
342 // system process is dead if we're here.
343 }
Mark Renouffec45da2019-03-13 13:24:27 -0400344 if (!isBubble) {
345 if (parentToCancelFinal != null) {
346 removeNotification(parentToCancelFinal);
347 }
348 if (shouldAutoCancel(sbn)
349 || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
350 notificationKey)) {
351 // Automatically remove all notifications that we may have kept around longer
352 removeNotification(sbn);
353 }
Gus Prevas21437b32018-12-05 10:36:13 -0500354 }
355 mIsCollapsingToShowActivityOverLockscreen = false;
356 }
357
Mark Renouffec45da2019-03-13 13:24:27 -0400358 private void expandBubbleStackOnMainThread(String notificationKey) {
359 if (Looper.getMainLooper().isCurrentThread()) {
360 mBubbleController.expandStackAndSelectBubble(notificationKey);
361 } else {
362 mMainThreadHandler.post(
363 () -> mBubbleController.expandStackAndSelectBubble(notificationKey));
364 }
365 }
366
Mark Renouf7bb6a242019-03-13 12:08:38 -0400367 private void startNotificationIntent(PendingIntent intent, Intent fillInIntent,
Evan Laird2ec752d2019-11-13 19:03:46 -0500368 View row, boolean wasOccluded, boolean isActivityIntent) {
Mark Renouf7bb6a242019-03-13 12:08:38 -0400369 RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row,
370 wasOccluded);
371 try {
372 if (adapter != null) {
373 ActivityTaskManager.getService()
374 .registerRemoteAnimationForNextActivityStart(
375 intent.getCreatorPackage(), adapter);
376 }
377 int launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
378 null, null, getActivityOptions(adapter));
379 mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
380 } catch (RemoteException | PendingIntent.CanceledException e) {
381 // the stack trace isn't very helpful here.
382 // Just log the exception message.
383 Log.w(TAG, "Sending contentIntent failed: " + e);
384 // TODO: Dismiss Keyguard.
385 }
386 }
387
Gus Prevas21437b32018-12-05 10:36:13 -0500388 @Override
389 public void startNotificationGutsIntent(final Intent intent, final int appUid,
390 ExpandableNotificationRow row) {
391 mActivityStarter.dismissKeyguardThenExecute(() -> {
392 AsyncTask.execute(() -> {
393 int launchResult = TaskStackBuilder.create(mContext)
394 .addNextIntentWithParentStack(intent)
395 .startActivities(getActivityOptions(
396 mActivityLaunchAnimator.getLaunchAnimation(
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800397 row, mStatusBar.isOccluded())),
Gus Prevas21437b32018-12-05 10:36:13 -0500398 new UserHandle(UserHandle.getUserId(appUid)));
399 mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
400 if (shouldCollapse()) {
401 // Putting it back on the main thread, since we're touching views
Mark Renouf6b2331c2019-03-21 13:40:08 -0400402 mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels(
Gus Prevas21437b32018-12-05 10:36:13 -0500403 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
404 }
405 });
406 return true;
407 }, null, false /* afterKeyguardGone */);
408 }
409
Ned Burnsf81c4c42019-01-07 14:10:43 -0500410 private void handleFullScreenIntent(NotificationEntry entry) {
Selim Cinekc3fec682019-06-06 18:11:07 -0700411 if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500412 if (shouldSuppressFullScreenIntent(entry)) {
413 if (DEBUG) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400414 Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
Gus Prevasd65c2db2018-12-18 17:13:38 -0500415 }
Ned Burns60e94592019-09-06 14:47:25 -0400416 } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500417 if (DEBUG) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400418 Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
Gus Prevasd65c2db2018-12-18 17:13:38 -0500419 }
420 } else {
421 // Stop screensaver if the notification has a fullscreen intent.
422 // (like an incoming phone call)
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500423 mUiBgExecutor.execute(() -> {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500424 try {
425 mDreamManager.awaken();
426 } catch (RemoteException e) {
427 e.printStackTrace();
428 }
429 });
430
431 // not immersive & a fullscreen alert should be shown
432 if (DEBUG) {
433 Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
434 }
435 try {
436 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400437 entry.getKey());
438 entry.getSbn().getNotification().fullScreenIntent.send();
Gus Prevasd65c2db2018-12-18 17:13:38 -0500439 entry.notifyFullScreenIntentLaunched();
440 mMetricsLogger.count("note_fullscreen", 1);
441 } catch (PendingIntent.CanceledException e) {
442 // ignore
443 }
444 }
445 }
446 }
447
Gus Prevas21437b32018-12-05 10:36:13 -0500448 @Override
449 public boolean isCollapsingToShowActivityOverLockscreen() {
450 return mIsCollapsingToShowActivityOverLockscreen;
451 }
452
453 private static boolean shouldAutoCancel(StatusBarNotification sbn) {
454 int flags = sbn.getNotification().flags;
455 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
456 return false;
457 }
458 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
459 return false;
460 }
461 return true;
462 }
463
464 private void collapseOnMainThread() {
465 if (Looper.getMainLooper().isCurrentThread()) {
466 mShadeController.collapsePanel();
467 } else {
Mark Renouf6b2331c2019-03-21 13:40:08 -0400468 mMainThreadHandler.post(mShadeController::collapsePanel);
Gus Prevas21437b32018-12-05 10:36:13 -0500469 }
470 }
471
472 private boolean shouldCollapse() {
473 return mStatusBarStateController.getState() != StatusBarState.SHADE
474 || !mActivityLaunchAnimator.isAnimationPending();
475 }
476
Ned Burnsf81c4c42019-01-07 14:10:43 -0500477 private boolean shouldSuppressFullScreenIntent(NotificationEntry entry) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500478 if (mPresenter.isDeviceInVrMode()) {
479 return true;
480 }
481
482 return entry.shouldSuppressFullScreenIntent();
483 }
484
Gus Prevas21437b32018-12-05 10:36:13 -0500485 private void removeNotification(StatusBarNotification notification) {
486 // We have to post it to the UI thread for synchronization
Mark Renouf6b2331c2019-03-21 13:40:08 -0400487 mMainThreadHandler.post(() -> {
Gus Prevas21437b32018-12-05 10:36:13 -0500488 Runnable removeRunnable =
Mady Mellorc2ff0112019-03-28 14:18:06 -0700489 () -> mEntryManager.performRemoveNotification(notification, REASON_CLICK);
Gus Prevas21437b32018-12-05 10:36:13 -0500490 if (mPresenter.isCollapsing()) {
491 // To avoid lags we're only performing the remove
492 // after the shade was collapsed
493 mShadeController.addPostCollapseAction(removeRunnable);
494 } else {
495 removeRunnable.run();
496 }
497 });
498 }
Dave Mankoff4c73e652019-11-14 17:39:08 -0500499
500 /**
501 * Public builder for {@link StatusBarNotificationActivityStarter}.
502 */
503 @Singleton
504 public static class Builder {
505 private final Context mContext;
506 private final CommandQueue mCommandQueue;
507 private final Lazy<AssistManager> mAssistManagerLazy;
508 private final NotificationEntryManager mEntryManager;
509 private final HeadsUpManagerPhone mHeadsUpManager;
510 private final ActivityStarter mActivityStarter;
511 private final IStatusBarService mStatusBarService;
512 private final StatusBarStateController mStatusBarStateController;
Heemin Seog98df6972019-12-05 13:01:38 -0800513 private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500514 private final KeyguardManager mKeyguardManager;
515 private final IDreamManager mDreamManager;
516 private final NotificationRemoteInputManager mRemoteInputManager;
517 private final StatusBarRemoteInputCallback mRemoteInputCallback;
518 private final NotificationGroupManager mGroupManager;
519 private final NotificationLockscreenUserManager mLockscreenUserManager;
520 private final KeyguardStateController mKeyguardStateController;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500521 private final MetricsLogger mMetricsLogger;
522 private final LockPatternUtils mLockPatternUtils;
523 private final Handler mMainThreadHandler;
524 private final Handler mBackgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500525 private final Executor mUiBgExecutor;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500526 private final ActivityIntentHelper mActivityIntentHelper;
527 private final BubbleController mBubbleController;
Dave Mankoff59b94962019-12-16 16:42:15 -0500528 private NotificationPanelViewController mNotificationPanelViewController;
529 private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
Heemin Seogba6337f2019-12-10 15:34:37 -0800530 private final ShadeController mShadeController;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500531 private NotificationPresenter mNotificationPresenter;
532 private ActivityLaunchAnimator mActivityLaunchAnimator;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800533 private StatusBar mStatusBar;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500534
535 @Inject
536 public Builder(Context context,
537 CommandQueue commandQueue,
538 Lazy<AssistManager> assistManagerLazy,
539 NotificationEntryManager entryManager,
540 HeadsUpManagerPhone headsUpManager,
541 ActivityStarter activityStarter,
542 IStatusBarService statusBarService,
543 StatusBarStateController statusBarStateController,
Heemin Seog98df6972019-12-05 13:01:38 -0800544 StatusBarKeyguardViewManager statusBarKeyguardViewManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500545 KeyguardManager keyguardManager,
546 IDreamManager dreamManager,
547 NotificationRemoteInputManager remoteInputManager,
548 StatusBarRemoteInputCallback remoteInputCallback,
549 NotificationGroupManager groupManager,
550 NotificationLockscreenUserManager lockscreenUserManager,
551 KeyguardStateController keyguardStateController,
552 NotificationInterruptionStateProvider notificationInterruptionStateProvider,
553 MetricsLogger metricsLogger,
554 LockPatternUtils lockPatternUtils,
Dave Mankoff00e8a2f2019-12-18 16:59:49 -0500555 @Main Handler mainThreadHandler,
556 @Background Handler backgroundHandler,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500557 @UiBackground Executor uiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500558 ActivityIntentHelper activityIntentHelper,
559 BubbleController bubbleController,
Dave Mankoff59b94962019-12-16 16:42:15 -0500560 ShadeController shadeController) {
Dave Mankoff4c73e652019-11-14 17:39:08 -0500561 mContext = context;
562 mCommandQueue = commandQueue;
563 mAssistManagerLazy = assistManagerLazy;
564 mEntryManager = entryManager;
565 mHeadsUpManager = headsUpManager;
566 mActivityStarter = activityStarter;
567 mStatusBarService = statusBarService;
568 mStatusBarStateController = statusBarStateController;
Heemin Seog98df6972019-12-05 13:01:38 -0800569 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500570 mKeyguardManager = keyguardManager;
571 mDreamManager = dreamManager;
572 mRemoteInputManager = remoteInputManager;
573 mRemoteInputCallback = remoteInputCallback;
574 mGroupManager = groupManager;
575 mLockscreenUserManager = lockscreenUserManager;
576 mKeyguardStateController = keyguardStateController;
577 mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
578 mMetricsLogger = metricsLogger;
579 mLockPatternUtils = lockPatternUtils;
580 mMainThreadHandler = mainThreadHandler;
581 mBackgroundHandler = backgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500582 mUiBgExecutor = uiBgExecutor;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500583 mActivityIntentHelper = activityIntentHelper;
584 mBubbleController = bubbleController;
Heemin Seogba6337f2019-12-10 15:34:37 -0800585 mShadeController = shadeController;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500586 }
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800587
Heemin Seogba6337f2019-12-10 15:34:37 -0800588 /** Sets the status bar to use as {@link StatusBar}. */
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800589 public Builder setStatusBar(StatusBar statusBar) {
590 mStatusBar = statusBar;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500591 return this;
592 }
593
594 public Builder setNotificationPresenter(NotificationPresenter notificationPresenter) {
595 mNotificationPresenter = notificationPresenter;
596 return this;
597 }
598
599 public Builder setActivityLaunchAnimator(ActivityLaunchAnimator activityLaunchAnimator) {
600 mActivityLaunchAnimator = activityLaunchAnimator;
601 return this;
602 }
603
Dave Mankoff59b94962019-12-16 16:42:15 -0500604 /** Set the NotificationPanelViewController */
605 public Builder setNotificationPanelViewController(
606 NotificationPanelViewController notificationPanelViewController) {
607 mNotificationPanelViewController = notificationPanelViewController;
608 return this;
609 }
610
611
612
Dave Mankoff4c73e652019-11-14 17:39:08 -0500613 public StatusBarNotificationActivityStarter build() {
614 return new StatusBarNotificationActivityStarter(mContext,
615 mCommandQueue, mAssistManagerLazy,
Dave Mankoff59b94962019-12-16 16:42:15 -0500616 mNotificationPanelViewController,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500617 mNotificationPresenter,
618 mEntryManager,
619 mHeadsUpManager,
620 mActivityStarter,
621 mActivityLaunchAnimator,
622 mStatusBarService,
623 mStatusBarStateController,
Heemin Seog98df6972019-12-05 13:01:38 -0800624 mStatusBarKeyguardViewManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500625 mKeyguardManager,
626 mDreamManager,
627 mRemoteInputManager,
628 mRemoteInputCallback,
629 mGroupManager,
630 mLockscreenUserManager,
631 mShadeController,
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800632 mStatusBar,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500633 mKeyguardStateController,
634 mNotificationInterruptionStateProvider,
635 mMetricsLogger,
636 mLockPatternUtils,
637 mMainThreadHandler,
638 mBackgroundHandler,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500639 mUiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500640 mActivityIntentHelper,
641 mBubbleController);
642 }
643 }
Gus Prevas21437b32018-12-05 10:36:13 -0500644}