blob: 661a7b1319a5ac2c59ef0ed62f7c3ba84fbf48ab [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;
Dave Mankoff4c73e652019-11-14 17:39:08 -050064import com.android.systemui.statusbar.SuperStatusBarViewFactory;
Gus Prevas21437b32018-12-05 10:36:13 -050065import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
66import com.android.systemui.statusbar.notification.NotificationActivityStarter;
Gus Prevasd65c2db2018-12-18 17:13:38 -050067import com.android.systemui.statusbar.notification.NotificationEntryListener;
Gus Prevas21437b32018-12-05 10:36:13 -050068import com.android.systemui.statusbar.notification.NotificationEntryManager;
Gus Prevasd65c2db2018-12-18 17:13:38 -050069import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
Ned Burnsf81c4c42019-01-07 14:10:43 -050070import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gustav Senntonf892fe92019-01-22 15:31:42 +000071import com.android.systemui.statusbar.notification.logging.NotificationLogger;
Gus Prevas21437b32018-12-05 10:36:13 -050072import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
73import com.android.systemui.statusbar.policy.HeadsUpUtil;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040074import com.android.systemui.statusbar.policy.KeyguardStateController;
Gus Prevas21437b32018-12-05 10:36:13 -050075
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -050076import java.util.concurrent.Executor;
77
Dave Mankoff4c73e652019-11-14 17:39:08 -050078import javax.inject.Inject;
79import javax.inject.Singleton;
80
81import dagger.Lazy;
82
Gus Prevas21437b32018-12-05 10:36:13 -050083/**
84 * Status bar implementation of {@link NotificationActivityStarter}.
85 */
86public class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
87
Evan Laird2ec752d2019-11-13 19:03:46 -050088 private static final String TAG = "NotifActivityStarter";
Gus Prevasd65c2db2018-12-18 17:13:38 -050089 protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Gus Prevas21437b32018-12-05 10:36:13 -050090
Dave Mankoff4c73e652019-11-14 17:39:08 -050091 private final Lazy<AssistManager> mAssistManagerLazy;
Mark Renouf906a93f2019-03-15 16:04:58 -040092 private final NotificationGroupManager mGroupManager;
93 private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
94 private final NotificationRemoteInputManager mRemoteInputManager;
95 private final NotificationLockscreenUserManager mLockscreenUserManager;
96 private final ShadeController mShadeController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -080097 private final StatusBar mStatusBar;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040098 private final KeyguardStateController mKeyguardStateController;
Mark Renouf906a93f2019-03-15 16:04:58 -040099 private final ActivityStarter mActivityStarter;
100 private final NotificationEntryManager mEntryManager;
101 private final StatusBarStateController mStatusBarStateController;
102 private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
103 private final MetricsLogger mMetricsLogger;
Gus Prevas21437b32018-12-05 10:36:13 -0500104 private final Context mContext;
105 private final NotificationPanelView mNotificationPanel;
106 private final NotificationPresenter mPresenter;
107 private final LockPatternUtils mLockPatternUtils;
108 private final HeadsUpManagerPhone mHeadsUpManager;
Heemin Seog98df6972019-12-05 13:01:38 -0800109 private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Gus Prevas21437b32018-12-05 10:36:13 -0500110 private final KeyguardManager mKeyguardManager;
111 private final ActivityLaunchAnimator mActivityLaunchAnimator;
112 private final IStatusBarService mBarService;
113 private final CommandQueue mCommandQueue;
Gus Prevasd65c2db2018-12-18 17:13:38 -0500114 private final IDreamManager mDreamManager;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400115 private final Handler mMainThreadHandler;
Mark Renouffec45da2019-03-13 13:24:27 -0400116 private final Handler mBackgroundHandler;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400117 private final ActivityIntentHelper mActivityIntentHelper;
Mark Renouffec45da2019-03-13 13:24:27 -0400118 private final BubbleController mBubbleController;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500119 private final Executor mUiBgExecutor;
Gus Prevas21437b32018-12-05 10:36:13 -0500120
121 private boolean mIsCollapsingToShowActivityOverLockscreen;
122
Dave Mankoff4c73e652019-11-14 17:39:08 -0500123 private StatusBarNotificationActivityStarter(Context context, CommandQueue commandQueue,
124 Lazy<AssistManager> assistManagerLazy, NotificationPanelView panel,
125 NotificationPresenter presenter, NotificationEntryManager entryManager,
126 HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter,
127 ActivityLaunchAnimator activityLaunchAnimator, IStatusBarService statusBarService,
Heemin Seog98df6972019-12-05 13:01:38 -0800128 StatusBarStateController statusBarStateController,
129 StatusBarKeyguardViewManager statusBarKeyguardViewManager,
130 KeyguardManager keyguardManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500131 IDreamManager dreamManager, NotificationRemoteInputManager remoteInputManager,
132 StatusBarRemoteInputCallback remoteInputCallback, NotificationGroupManager groupManager,
Mark Renouf906a93f2019-03-15 16:04:58 -0400133 NotificationLockscreenUserManager lockscreenUserManager,
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800134 ShadeController shadeController, StatusBar statusBar,
135 KeyguardStateController keyguardStateController,
Mark Renouf906a93f2019-03-15 16:04:58 -0400136 NotificationInterruptionStateProvider notificationInterruptionStateProvider,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500137 MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500138 Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500139 ActivityIntentHelper activityIntentHelper, BubbleController bubbleController) {
Gus Prevas21437b32018-12-05 10:36:13 -0500140 mContext = context;
141 mNotificationPanel = panel;
142 mPresenter = presenter;
Gus Prevas21437b32018-12-05 10:36:13 -0500143 mHeadsUpManager = headsUpManager;
Gus Prevas21437b32018-12-05 10:36:13 -0500144 mActivityLaunchAnimator = activityLaunchAnimator;
Mark Renouf906a93f2019-03-15 16:04:58 -0400145 mBarService = statusBarService;
146 mCommandQueue = commandQueue;
Heemin Seog98df6972019-12-05 13:01:38 -0800147 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
Mark Renouf906a93f2019-03-15 16:04:58 -0400148 mKeyguardManager = keyguardManager;
149 mDreamManager = dreamManager;
150 mRemoteInputManager = remoteInputManager;
151 mLockscreenUserManager = lockscreenUserManager;
152 mShadeController = shadeController;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800153 // TODO: use KeyguardStateController#isOccluded to remove this dependency
154 mStatusBar = statusBar;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400155 mKeyguardStateController = keyguardStateController;
Mark Renouf906a93f2019-03-15 16:04:58 -0400156 mActivityStarter = activityStarter;
157 mEntryManager = entryManager;
158 mStatusBarStateController = statusBarStateController;
159 mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
160 mMetricsLogger = metricsLogger;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500161 mAssistManagerLazy = assistManagerLazy;
Mark Renouf906a93f2019-03-15 16:04:58 -0400162 mGroupManager = groupManager;
163 mLockPatternUtils = lockPatternUtils;
Mark Renouffec45da2019-03-13 13:24:27 -0400164 mBackgroundHandler = backgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500165 mUiBgExecutor = uiBgExecutor;
Gus Prevasd65c2db2018-12-18 17:13:38 -0500166 mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
167 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -0500168 public void onPendingEntryAdded(NotificationEntry entry) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500169 handleFullScreenIntent(entry);
170 }
171 });
Mark Renouf906a93f2019-03-15 16:04:58 -0400172 mStatusBarRemoteInputCallback = remoteInputCallback;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400173 mMainThreadHandler = mainThreadHandler;
174 mActivityIntentHelper = activityIntentHelper;
Mark Renouffec45da2019-03-13 13:24:27 -0400175 mBubbleController = bubbleController;
Gus Prevas21437b32018-12-05 10:36:13 -0500176 }
177
178 /**
179 * Called when a notification is clicked.
180 *
181 * @param sbn notification that was clicked
182 * @param row row for that notification
183 */
184 @Override
185 public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
186 RemoteInputController controller = mRemoteInputManager.getController();
187 if (controller.isRemoteInputActive(row.getEntry())
188 && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
189 // We have an active remote input typed and the user clicked on the notification.
190 // this was probably unintentional, so we're closing the edit text instead.
191 controller.closeRemoteInputs();
192 return;
193 }
194 Notification notification = sbn.getNotification();
195 final PendingIntent intent = notification.contentIntent != null
196 ? notification.contentIntent
197 : notification.fullScreenIntent;
Mark Renouffec45da2019-03-13 13:24:27 -0400198 final boolean isBubble = row.getEntry().isBubble();
199
200 // This code path is now executed for notification without a contentIntent.
201 // The only valid case is Bubble notifications. Guard against other cases
202 // entering here.
203 if (intent == null && !isBubble) {
204 Log.e(TAG, "onNotificationClicked called for non-clickable notification!");
205 return;
206 }
207
Mark Renouffec45da2019-03-13 13:24:27 -0400208 boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
Gus Prevas21437b32018-12-05 10:36:13 -0500209 final boolean afterKeyguardGone = isActivityIntent
Mark Renouf6b2331c2019-03-21 13:40:08 -0400210 && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
Gus Prevas21437b32018-12-05 10:36:13 -0500211 mLockscreenUserManager.getCurrentUserId());
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800212 final boolean wasOccluded = mStatusBar.isOccluded();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400213 boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
Mark Renouf6b2331c2019-03-21 13:40:08 -0400214 && mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
Gus Prevas21437b32018-12-05 10:36:13 -0500215 mLockscreenUserManager.getCurrentUserId());
216 ActivityStarter.OnDismissAction postKeyguardAction =
217 () -> handleNotificationClickAfterKeyguardDismissed(
Evan Laird2ec752d2019-11-13 19:03:46 -0500218 sbn, row, controller, intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500219 isActivityIntent, wasOccluded, showOverLockscreen);
220 if (showOverLockscreen) {
221 mIsCollapsingToShowActivityOverLockscreen = true;
222 postKeyguardAction.onDismiss();
223 } else {
224 mActivityStarter.dismissKeyguardThenExecute(
225 postKeyguardAction, null /* cancel */, afterKeyguardGone);
226 }
227 }
228
229 private boolean handleNotificationClickAfterKeyguardDismissed(
230 StatusBarNotification sbn,
231 ExpandableNotificationRow row,
232 RemoteInputController controller,
233 PendingIntent intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500234 boolean isActivityIntent,
235 boolean wasOccluded,
236 boolean showOverLockscreen) {
237 // TODO: Some of this code may be able to move to NotificationEntryManager.
Evan Laird2ec752d2019-11-13 19:03:46 -0500238 if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(sbn.getKey())) {
Gus Prevas21437b32018-12-05 10:36:13 -0500239 // Release the HUN notification to the shade.
240
241 if (mPresenter.isPresenterFullyCollapsed()) {
242 HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
243 }
244 //
245 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
246 // become canceled shortly by NoMan, but we can't assume that.
247 mHeadsUpManager.removeNotification(sbn.getKey(),
248 true /* releaseImmediately */);
249 }
250 StatusBarNotification parentToCancel = null;
251 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
252 StatusBarNotification summarySbn =
Ned Burns00b4b2d2019-10-17 22:09:27 -0400253 mGroupManager.getLogicalGroupSummary(sbn).getSbn();
Gus Prevas21437b32018-12-05 10:36:13 -0500254 if (shouldAutoCancel(summarySbn)) {
255 parentToCancel = summarySbn;
256 }
257 }
258 final StatusBarNotification parentToCancelFinal = parentToCancel;
259 final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
Evan Laird2ec752d2019-11-13 19:03:46 -0500260 sbn, row, controller, intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500261 isActivityIntent, wasOccluded, parentToCancelFinal);
262
263 if (showOverLockscreen) {
264 mShadeController.addPostCollapseAction(runnable);
265 mShadeController.collapsePanel(true /* animate */);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400266 } else if (mKeyguardStateController.isShowing()
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800267 && mStatusBar.isOccluded()) {
Heemin Seog98df6972019-12-05 13:01:38 -0800268 mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
Gus Prevas21437b32018-12-05 10:36:13 -0500269 mShadeController.collapsePanel();
270 } else {
Mark Renouffec45da2019-03-13 13:24:27 -0400271 mBackgroundHandler.postAtFrontOfQueue(runnable);
Gus Prevas21437b32018-12-05 10:36:13 -0500272 }
Gus Prevas21437b32018-12-05 10:36:13 -0500273 return !mNotificationPanel.isFullyCollapsed();
274 }
275
276 private void handleNotificationClickAfterPanelCollapsed(
277 StatusBarNotification sbn,
278 ExpandableNotificationRow row,
279 RemoteInputController controller,
280 PendingIntent intent,
Gus Prevas21437b32018-12-05 10:36:13 -0500281 boolean isActivityIntent,
282 boolean wasOccluded,
283 StatusBarNotification parentToCancelFinal) {
Evan Laird2ec752d2019-11-13 19:03:46 -0500284 String notificationKey = sbn.getKey();
Gus Prevas21437b32018-12-05 10:36:13 -0500285 try {
286 // The intent we are sending is for the application, which
287 // won't have permission to immediately start an activity after
288 // the user switches to home. We know it is safe to do at this
289 // point, so make sure new activity switches are now allowed.
290 ActivityManager.getService().resumeAppSwitches();
291 } catch (RemoteException e) {
292 }
Gus Prevas21437b32018-12-05 10:36:13 -0500293 // If we are launching a work activity and require to launch
294 // separate work challenge, we defer the activity action and cancel
295 // notification until work challenge is unlocked.
296 if (isActivityIntent) {
297 final int userId = intent.getCreatorUserHandle().getIdentifier();
298 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
299 && mKeyguardManager.isDeviceLocked(userId)) {
300 // TODO(b/28935539): should allow certain activities to
301 // bypass work challenge
302 if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
303 intent.getIntentSender(), notificationKey)) {
304 // Show work challenge, do not run PendingIntent and
305 // remove notification
306 collapseOnMainThread();
307 return;
308 }
309 }
310 }
311 Intent fillInIntent = null;
Ned Burnsf81c4c42019-01-07 14:10:43 -0500312 NotificationEntry entry = row.getEntry();
Mark Renouffec45da2019-03-13 13:24:27 -0400313 final boolean isBubble = entry.isBubble();
Gus Prevas21437b32018-12-05 10:36:13 -0500314 CharSequence remoteInputText = null;
315 if (!TextUtils.isEmpty(entry.remoteInputText)) {
316 remoteInputText = entry.remoteInputText;
317 }
Evan Laird2ec752d2019-11-13 19:03:46 -0500318 if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(notificationKey)) {
Gus Prevas21437b32018-12-05 10:36:13 -0500319 fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
320 remoteInputText.toString());
321 }
Mark Renouffec45da2019-03-13 13:24:27 -0400322 if (isBubble) {
323 expandBubbleStackOnMainThread(notificationKey);
324 } else {
325 startNotificationIntent(intent, fillInIntent, row, wasOccluded, isActivityIntent);
326 }
327 if (isActivityIntent || isBubble) {
Dave Mankoff4c73e652019-11-14 17:39:08 -0500328 mAssistManagerLazy.get().hideAssist();
Gus Prevas21437b32018-12-05 10:36:13 -0500329 }
330 if (shouldCollapse()) {
331 collapseOnMainThread();
332 }
333
Evan Laird181de622019-10-24 09:53:02 -0400334 final int count = mEntryManager.getActiveNotificationsCount();
Evan Laird2ec752d2019-11-13 19:03:46 -0500335 final int rank = entry.getRanking().getRank();
Gustav Senntonf892fe92019-01-22 15:31:42 +0000336 NotificationVisibility.NotificationLocation location =
Evan Laird2ec752d2019-11-13 19:03:46 -0500337 NotificationLogger.getNotificationLocation(entry);
Gus Prevas21437b32018-12-05 10:36:13 -0500338 final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
Gustav Senntonf892fe92019-01-22 15:31:42 +0000339 rank, count, true, location);
Gus Prevas21437b32018-12-05 10:36:13 -0500340 try {
341 mBarService.onNotificationClick(notificationKey, nv);
342 } catch (RemoteException ex) {
343 // system process is dead if we're here.
344 }
Mark Renouffec45da2019-03-13 13:24:27 -0400345 if (!isBubble) {
346 if (parentToCancelFinal != null) {
347 removeNotification(parentToCancelFinal);
348 }
349 if (shouldAutoCancel(sbn)
350 || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
351 notificationKey)) {
352 // Automatically remove all notifications that we may have kept around longer
353 removeNotification(sbn);
354 }
Gus Prevas21437b32018-12-05 10:36:13 -0500355 }
356 mIsCollapsingToShowActivityOverLockscreen = false;
357 }
358
Mark Renouffec45da2019-03-13 13:24:27 -0400359 private void expandBubbleStackOnMainThread(String notificationKey) {
360 if (Looper.getMainLooper().isCurrentThread()) {
361 mBubbleController.expandStackAndSelectBubble(notificationKey);
362 } else {
363 mMainThreadHandler.post(
364 () -> mBubbleController.expandStackAndSelectBubble(notificationKey));
365 }
366 }
367
Mark Renouf7bb6a242019-03-13 12:08:38 -0400368 private void startNotificationIntent(PendingIntent intent, Intent fillInIntent,
Evan Laird2ec752d2019-11-13 19:03:46 -0500369 View row, boolean wasOccluded, boolean isActivityIntent) {
Mark Renouf7bb6a242019-03-13 12:08:38 -0400370 RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row,
371 wasOccluded);
372 try {
373 if (adapter != null) {
374 ActivityTaskManager.getService()
375 .registerRemoteAnimationForNextActivityStart(
376 intent.getCreatorPackage(), adapter);
377 }
378 int launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
379 null, null, getActivityOptions(adapter));
380 mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
381 } catch (RemoteException | PendingIntent.CanceledException e) {
382 // the stack trace isn't very helpful here.
383 // Just log the exception message.
384 Log.w(TAG, "Sending contentIntent failed: " + e);
385 // TODO: Dismiss Keyguard.
386 }
387 }
388
Gus Prevas21437b32018-12-05 10:36:13 -0500389 @Override
390 public void startNotificationGutsIntent(final Intent intent, final int appUid,
391 ExpandableNotificationRow row) {
392 mActivityStarter.dismissKeyguardThenExecute(() -> {
393 AsyncTask.execute(() -> {
394 int launchResult = TaskStackBuilder.create(mContext)
395 .addNextIntentWithParentStack(intent)
396 .startActivities(getActivityOptions(
397 mActivityLaunchAnimator.getLaunchAnimation(
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800398 row, mStatusBar.isOccluded())),
Gus Prevas21437b32018-12-05 10:36:13 -0500399 new UserHandle(UserHandle.getUserId(appUid)));
400 mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
401 if (shouldCollapse()) {
402 // Putting it back on the main thread, since we're touching views
Mark Renouf6b2331c2019-03-21 13:40:08 -0400403 mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels(
Gus Prevas21437b32018-12-05 10:36:13 -0500404 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
405 }
406 });
407 return true;
408 }, null, false /* afterKeyguardGone */);
409 }
410
Ned Burnsf81c4c42019-01-07 14:10:43 -0500411 private void handleFullScreenIntent(NotificationEntry entry) {
Selim Cinekc3fec682019-06-06 18:11:07 -0700412 if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500413 if (shouldSuppressFullScreenIntent(entry)) {
414 if (DEBUG) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400415 Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
Gus Prevasd65c2db2018-12-18 17:13:38 -0500416 }
Ned Burns60e94592019-09-06 14:47:25 -0400417 } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500418 if (DEBUG) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400419 Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
Gus Prevasd65c2db2018-12-18 17:13:38 -0500420 }
421 } else {
422 // Stop screensaver if the notification has a fullscreen intent.
423 // (like an incoming phone call)
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500424 mUiBgExecutor.execute(() -> {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500425 try {
426 mDreamManager.awaken();
427 } catch (RemoteException e) {
428 e.printStackTrace();
429 }
430 });
431
432 // not immersive & a fullscreen alert should be shown
433 if (DEBUG) {
434 Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
435 }
436 try {
437 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
Ned Burns00b4b2d2019-10-17 22:09:27 -0400438 entry.getKey());
439 entry.getSbn().getNotification().fullScreenIntent.send();
Gus Prevasd65c2db2018-12-18 17:13:38 -0500440 entry.notifyFullScreenIntentLaunched();
441 mMetricsLogger.count("note_fullscreen", 1);
442 } catch (PendingIntent.CanceledException e) {
443 // ignore
444 }
445 }
446 }
447 }
448
Gus Prevas21437b32018-12-05 10:36:13 -0500449 @Override
450 public boolean isCollapsingToShowActivityOverLockscreen() {
451 return mIsCollapsingToShowActivityOverLockscreen;
452 }
453
454 private static boolean shouldAutoCancel(StatusBarNotification sbn) {
455 int flags = sbn.getNotification().flags;
456 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
457 return false;
458 }
459 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
460 return false;
461 }
462 return true;
463 }
464
465 private void collapseOnMainThread() {
466 if (Looper.getMainLooper().isCurrentThread()) {
467 mShadeController.collapsePanel();
468 } else {
Mark Renouf6b2331c2019-03-21 13:40:08 -0400469 mMainThreadHandler.post(mShadeController::collapsePanel);
Gus Prevas21437b32018-12-05 10:36:13 -0500470 }
471 }
472
473 private boolean shouldCollapse() {
474 return mStatusBarStateController.getState() != StatusBarState.SHADE
475 || !mActivityLaunchAnimator.isAnimationPending();
476 }
477
Ned Burnsf81c4c42019-01-07 14:10:43 -0500478 private boolean shouldSuppressFullScreenIntent(NotificationEntry entry) {
Gus Prevasd65c2db2018-12-18 17:13:38 -0500479 if (mPresenter.isDeviceInVrMode()) {
480 return true;
481 }
482
483 return entry.shouldSuppressFullScreenIntent();
484 }
485
Gus Prevas21437b32018-12-05 10:36:13 -0500486 private void removeNotification(StatusBarNotification notification) {
487 // We have to post it to the UI thread for synchronization
Mark Renouf6b2331c2019-03-21 13:40:08 -0400488 mMainThreadHandler.post(() -> {
Gus Prevas21437b32018-12-05 10:36:13 -0500489 Runnable removeRunnable =
Mady Mellorc2ff0112019-03-28 14:18:06 -0700490 () -> mEntryManager.performRemoveNotification(notification, REASON_CLICK);
Gus Prevas21437b32018-12-05 10:36:13 -0500491 if (mPresenter.isCollapsing()) {
492 // To avoid lags we're only performing the remove
493 // after the shade was collapsed
494 mShadeController.addPostCollapseAction(removeRunnable);
495 } else {
496 removeRunnable.run();
497 }
498 });
499 }
Dave Mankoff4c73e652019-11-14 17:39:08 -0500500
501 /**
502 * Public builder for {@link StatusBarNotificationActivityStarter}.
503 */
504 @Singleton
505 public static class Builder {
506 private final Context mContext;
507 private final CommandQueue mCommandQueue;
508 private final Lazy<AssistManager> mAssistManagerLazy;
509 private final NotificationEntryManager mEntryManager;
510 private final HeadsUpManagerPhone mHeadsUpManager;
511 private final ActivityStarter mActivityStarter;
512 private final IStatusBarService mStatusBarService;
513 private final StatusBarStateController mStatusBarStateController;
Heemin Seog98df6972019-12-05 13:01:38 -0800514 private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500515 private final KeyguardManager mKeyguardManager;
516 private final IDreamManager mDreamManager;
517 private final NotificationRemoteInputManager mRemoteInputManager;
518 private final StatusBarRemoteInputCallback mRemoteInputCallback;
519 private final NotificationGroupManager mGroupManager;
520 private final NotificationLockscreenUserManager mLockscreenUserManager;
521 private final KeyguardStateController mKeyguardStateController;
522 private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
523 private final MetricsLogger mMetricsLogger;
524 private final LockPatternUtils mLockPatternUtils;
525 private final Handler mMainThreadHandler;
526 private final Handler mBackgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500527 private final Executor mUiBgExecutor;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500528 private final ActivityIntentHelper mActivityIntentHelper;
529 private final BubbleController mBubbleController;
530 private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
Heemin Seogba6337f2019-12-10 15:34:37 -0800531 private final ShadeController mShadeController;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500532 private NotificationPresenter mNotificationPresenter;
533 private ActivityLaunchAnimator mActivityLaunchAnimator;
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800534 private StatusBar mStatusBar;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500535
536 @Inject
537 public Builder(Context context,
538 CommandQueue commandQueue,
539 Lazy<AssistManager> assistManagerLazy,
540 NotificationEntryManager entryManager,
541 HeadsUpManagerPhone headsUpManager,
542 ActivityStarter activityStarter,
543 IStatusBarService statusBarService,
544 StatusBarStateController statusBarStateController,
Heemin Seog98df6972019-12-05 13:01:38 -0800545 StatusBarKeyguardViewManager statusBarKeyguardViewManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500546 KeyguardManager keyguardManager,
547 IDreamManager dreamManager,
548 NotificationRemoteInputManager remoteInputManager,
549 StatusBarRemoteInputCallback remoteInputCallback,
550 NotificationGroupManager groupManager,
551 NotificationLockscreenUserManager lockscreenUserManager,
552 KeyguardStateController keyguardStateController,
553 NotificationInterruptionStateProvider notificationInterruptionStateProvider,
554 MetricsLogger metricsLogger,
555 LockPatternUtils lockPatternUtils,
Dave Mankoff00e8a2f2019-12-18 16:59:49 -0500556 @Main Handler mainThreadHandler,
557 @Background Handler backgroundHandler,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500558 @UiBackground Executor uiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500559 ActivityIntentHelper activityIntentHelper,
560 BubbleController bubbleController,
Heemin Seogba6337f2019-12-10 15:34:37 -0800561 ShadeController shadeController,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500562 SuperStatusBarViewFactory superStatusBarViewFactory) {
563 mContext = context;
564 mCommandQueue = commandQueue;
565 mAssistManagerLazy = assistManagerLazy;
566 mEntryManager = entryManager;
567 mHeadsUpManager = headsUpManager;
568 mActivityStarter = activityStarter;
569 mStatusBarService = statusBarService;
570 mStatusBarStateController = statusBarStateController;
Heemin Seog98df6972019-12-05 13:01:38 -0800571 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500572 mKeyguardManager = keyguardManager;
573 mDreamManager = dreamManager;
574 mRemoteInputManager = remoteInputManager;
575 mRemoteInputCallback = remoteInputCallback;
576 mGroupManager = groupManager;
577 mLockscreenUserManager = lockscreenUserManager;
578 mKeyguardStateController = keyguardStateController;
579 mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
580 mMetricsLogger = metricsLogger;
581 mLockPatternUtils = lockPatternUtils;
582 mMainThreadHandler = mainThreadHandler;
583 mBackgroundHandler = backgroundHandler;
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500584 mUiBgExecutor = uiBgExecutor;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500585 mActivityIntentHelper = activityIntentHelper;
586 mBubbleController = bubbleController;
Heemin Seogba6337f2019-12-10 15:34:37 -0800587 mShadeController = shadeController;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500588 mSuperStatusBarViewFactory = superStatusBarViewFactory;
589 }
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800590
Heemin Seogba6337f2019-12-10 15:34:37 -0800591 /** Sets the status bar to use as {@link StatusBar}. */
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800592 public Builder setStatusBar(StatusBar statusBar) {
593 mStatusBar = statusBar;
Dave Mankoff4c73e652019-11-14 17:39:08 -0500594 return this;
595 }
596
597 public Builder setNotificationPresenter(NotificationPresenter notificationPresenter) {
598 mNotificationPresenter = notificationPresenter;
599 return this;
600 }
601
602 public Builder setActivityLaunchAnimator(ActivityLaunchAnimator activityLaunchAnimator) {
603 mActivityLaunchAnimator = activityLaunchAnimator;
604 return this;
605 }
606
607 public StatusBarNotificationActivityStarter build() {
608 return new StatusBarNotificationActivityStarter(mContext,
609 mCommandQueue, mAssistManagerLazy,
610 mSuperStatusBarViewFactory.getNotificationPanelView(),
611 mNotificationPresenter,
612 mEntryManager,
613 mHeadsUpManager,
614 mActivityStarter,
615 mActivityLaunchAnimator,
616 mStatusBarService,
617 mStatusBarStateController,
Heemin Seog98df6972019-12-05 13:01:38 -0800618 mStatusBarKeyguardViewManager,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500619 mKeyguardManager,
620 mDreamManager,
621 mRemoteInputManager,
622 mRemoteInputCallback,
623 mGroupManager,
624 mLockscreenUserManager,
625 mShadeController,
Heemin Seogbd9bcbf2019-12-04 17:07:32 -0800626 mStatusBar,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500627 mKeyguardStateController,
628 mNotificationInterruptionStateProvider,
629 mMetricsLogger,
630 mLockPatternUtils,
631 mMainThreadHandler,
632 mBackgroundHandler,
Dave Mankoffc7cf9fc2019-12-19 15:43:20 -0500633 mUiBgExecutor,
Dave Mankoff4c73e652019-11-14 17:39:08 -0500634 mActivityIntentHelper,
635 mBubbleController);
636 }
637 }
Gus Prevas21437b32018-12-05 10:36:13 -0500638}