Extracts NotificationActivityStarter from NotificationPresenter.

This change simplifies the NotificationPresenter interface by extracting
the methods dealing with starting an activity due to actions taken on a
notification to a separate interface, NotificationActivityStarter.
The extracted methods in StatusBarNotificationActivityStarter are also
cleaned up to make the control flow easier to read.
Pure refactor; no functional changes.

Test: atest SystemUITests
Change-Id: I2e8cf0626a005dc52b9969865a097cc14da9b669
This commit is contained in:
Gus Prevas
2018-12-05 10:36:13 -05:00
parent 7796107b0b
commit 21437b3abb
14 changed files with 487 additions and 356 deletions

View File

@@ -15,9 +15,6 @@
*/
package com.android.systemui.statusbar;
import android.content.Intent;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -38,12 +35,6 @@ public interface NotificationPresenter extends ExpandableNotificationRow.OnExpan
*/
boolean isPresenterFullyCollapsed();
/**
* Runs the given intent. The presenter may want to run some animations or close itself when
* this happens.
*/
void startNotificationGutsIntent(Intent intent, int appUid, ExpandableNotificationRow row);
/**
* Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
*/
@@ -74,8 +65,7 @@ public interface NotificationPresenter extends ExpandableNotificationRow.OnExpan
int getMaxNotificationsWhileLocked(boolean recompute);
/**
* True if the presenter
* @return
* True if the presenter is currently locked.
*/
default boolean isPresenterLocked() { return false; }
@@ -88,22 +78,4 @@ public interface NotificationPresenter extends ExpandableNotificationRow.OnExpan
* @return true if the shade is collapsing.
*/
boolean isCollapsing();
/**
* @return true if the shade is collapsing to show an activity over the lock screen
*/
default public boolean isCollapsingToShowActivityOverLockscreen() {
return false;
}
/**
* Get the {@link ActivityLaunchAnimator} from the presenter so it can be queried by
* {@link com.android.systemui.statusbar.phone.StatusBar}
* @return the current animator
* @deprecated This is only here for now because StatusBar is still the ActivityLaunchAnimator
* callback but shouldn't be.
*/
default public ActivityLaunchAnimator getActivityLaunchAnimator() {
return null;
}
}

View File

@@ -111,7 +111,6 @@ public class NotificationRemoteInputManager implements Dumpable {
private final KeyguardManager mKeyguardManager;
protected RemoteInputController mRemoteInputController;
protected NotificationPresenter mPresenter;
protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
mNotificationLifetimeFinishedCallback;
protected IStatusBarService mBarService;
@@ -320,10 +319,8 @@ public class NotificationRemoteInputManager implements Dumpable {
mKeyguardManager = context.getSystemService(KeyguardManager.class);
}
public void setUpWithPresenter(NotificationPresenter presenter,
Callback callback,
RemoteInputController.Delegate delegate) {
mPresenter = presenter;
/** Initializes this component with the provided dependencies. */
public void setUpWithCallback(Callback callback, RemoteInputController.Delegate delegate) {
mCallback = callback;
mRemoteInputController = new RemoteInputController(delegate);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification;
import android.content.Intent;
import android.service.notification.StatusBarNotification;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* Component responsible for handling actions on a notification which cause activites to start.
* (e.g. clicking on a notification, tapping on the settings icon in the notification guts)
*/
public interface NotificationActivityStarter {
/** Called when the user clicks on the surface of a notification. */
void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row);
/** Called when the user clicks on a button in the notification guts which fires an intent. */
void startNotificationGutsIntent(Intent intent, int appUid,
ExpandableNotificationRow row);
default boolean isCollapsingToShowActivityOverLockscreen() {
return false;
}
}

View File

@@ -143,6 +143,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
protected IStatusBarService mBarService;
private NotificationPresenter mPresenter;
private Callback mCallback;
private NotificationActivityStarter mNotificationActivityStarter;
protected PowerManager mPowerManager;
private NotificationListenerService.RankingMap mLatestRankingMap;
protected HeadsUpManager mHeadsUpManager;
@@ -193,7 +194,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mBubbleController.collapseStack();
}
mCallback.onNotificationClicked(sbn, row);
mNotificationActivityStarter.onNotificationClicked(sbn, row);
}
private boolean isMenuVisible(ExpandableNotificationRow row) {
@@ -346,6 +347,11 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mOnAppOpsClickListener = mGutsManager::openGuts;
}
public void setNotificationActivityStarter(
NotificationActivityStarter notificationActivityStarter) {
mNotificationActivityStarter = notificationActivityStarter;
}
public NotificationData getNotificationData() {
return mNotificationData;
}
@@ -1247,15 +1253,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
*/
void onNotificationRemoved(String key, StatusBarNotification old);
/**
* Called when a notification is clicked.
*
* @param sbn notification that was clicked
* @param row row for that notification
*/
void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row);
/**
* Called when a new notification and row is created.
*

View File

@@ -25,7 +25,6 @@ import android.app.NotificationChannel;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -42,13 +41,13 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -79,13 +78,13 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
Dependency.get(StatusBarStateController.class);
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
// which notification is currently being longpress-examined by the user
private NotificationGuts mNotificationGutsExposed;
private NotificationMenuRowPlugin.MenuItem mGutsMenuItem;
private NotificationSafeToRemoveCallback mNotificationLifetimeFinishedCallback;
private NotificationPresenter mPresenter;
private NotificationActivityStarter mNotificationActivityStarter;
private NotificationListContainer mListContainer;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@@ -94,8 +93,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
public NotificationGutsManager(Context context) {
mContext = context;
Resources res = context.getResources();
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
@@ -109,6 +106,11 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mOnSettingsClickListener = onSettingsClick;
}
public void setNotificationActivityStarter(
NotificationActivityStarter notificationActivityStarter) {
mNotificationActivityStarter = notificationActivityStarter;
}
public void onDensityOrFontScaleChanged(NotificationData.Entry entry) {
setExposedGuts(entry.getGuts());
bindGuts(entry.getRow());
@@ -127,7 +129,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
if (channel != null) {
intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
}
mPresenter.startNotificationGutsIntent(intent, appUid, row);
mNotificationActivityStarter.startNotificationGutsIntent(intent, appUid, row);
}
protected void startAppOpsSettingsActivity(String pkg, int uid, ArraySet<Integer> ops,
@@ -138,12 +140,12 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
} else {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.fromParts("package", pkg, null));
mPresenter.startNotificationGutsIntent(intent, uid, row);
mNotificationActivityStarter.startNotificationGutsIntent(intent, uid, row);
}
} else if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, pkg);
mPresenter.startNotificationGutsIntent(intent, uid, row);
mNotificationActivityStarter.startNotificationGutsIntent(intent, uid, row);
}
}
@@ -262,7 +264,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
(View v, Intent intent) -> {
mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_APP_NOTE_SETTINGS);
guts.resetFalsingCheck();
mPresenter.startNotificationGutsIntent(intent, sbn.getUid(), row);
mNotificationActivityStarter.startNotificationGutsIntent(intent, sbn.getUid(),
row);
};
boolean isForBlockingHelper = row.isBlockingHelperShowing();

View File

@@ -187,6 +187,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -578,7 +579,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private boolean mVibrateOnOpening;
private VibratorHelper mVibratorHelper;
private ActivityLaunchAnimator mActivityLaunchAnimator;
protected NotificationPresenter mPresenter;
private NotificationActivityStarter mNotificationActivityStarter;
private boolean mPulsing;
@Override
@@ -1014,13 +1017,23 @@ public class StatusBar extends SystemUI implements DemoMode,
protected void setUpPresenter() {
// Set up the initial notification state.
mActivityLaunchAnimator = new ActivityLaunchAnimator(
mStatusBarWindow, this, mNotificationPanel,
(NotificationListContainer) mStackScroller);
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, this);
mScrimController, mActivityLaunchAnimator);
mAppOpsController.addCallback(APP_OPS, this);
mNotificationListener.setUpWithPresenter(mPresenter);
mNotificationShelf.setOnActivatedListener(mPresenter);
mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
mNotificationActivityStarter = new StatusBarNotificationActivityStarter(
mContext, mNotificationPanel, mPresenter, mHeadsUpManager, mActivityLaunchAnimator);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
mEntryManager.setNotificationActivityStarter(mNotificationActivityStarter);
}
/**
@@ -1639,9 +1652,9 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onExpandAnimationTimedOut() {
ActivityLaunchAnimator animator = mPresenter.getActivityLaunchAnimator();
if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
&& animator != null && !animator.isLaunchForActivity()) {
&& mActivityLaunchAnimator != null
&& !mActivityLaunchAnimator.isLaunchForActivity()) {
onClosingFinished();
} else {
collapsePanel(true /* animate */);
@@ -1940,7 +1953,7 @@ public class StatusBar extends SystemUI implements DemoMode,
runPostCollapseRunnables();
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
if (!mPresenter.isCollapsingToShowActivityOverLockscreen()) {
if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
showBouncerIfKeyguard();
} else if (DEBUG) {
Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");

View File

@@ -0,0 +1,368 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.phone;
import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.view.RemoteAnimationAdapter;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.PreviewInflater;
/**
* Status bar implementation of {@link NotificationActivityStarter}.
*/
public class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
private static final String TAG = "NotificationClickHandler";
private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
(StatusBarRemoteInputCallback) Dependency.get(
NotificationRemoteInputManager.Callback.class);
private final NotificationRemoteInputManager mRemoteInputManager =
Dependency.get(NotificationRemoteInputManager.class);
private final NotificationLockscreenUserManager mLockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
private final StatusBarStateController mStatusBarStateController =
Dependency.get(StatusBarStateController.class);
private final Context mContext;
private final NotificationPanelView mNotificationPanel;
private final NotificationPresenter mPresenter;
private final LockPatternUtils mLockPatternUtils;
private final HeadsUpManagerPhone mHeadsUpManager;
private final KeyguardManager mKeyguardManager;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final IStatusBarService mBarService;
private final CommandQueue mCommandQueue;
private boolean mIsCollapsingToShowActivityOverLockscreen;
public StatusBarNotificationActivityStarter(Context context,
NotificationPanelView panel,
NotificationPresenter presenter,
HeadsUpManagerPhone headsUpManager,
ActivityLaunchAnimator activityLaunchAnimator) {
mContext = context;
mNotificationPanel = panel;
mPresenter = presenter;
mLockPatternUtils = new LockPatternUtils(context);
mHeadsUpManager = headsUpManager;
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mActivityLaunchAnimator = activityLaunchAnimator;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mCommandQueue = getComponent(context, CommandQueue.class);
}
/**
* Called when a notification is clicked.
*
* @param sbn notification that was clicked
* @param row row for that notification
*/
@Override
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
RemoteInputController controller = mRemoteInputManager.getController();
if (controller.isRemoteInputActive(row.getEntry())
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
// We have an active remote input typed and the user clicked on the notification.
// this was probably unintentional, so we're closing the edit text instead.
controller.closeRemoteInputs();
return;
}
Notification notification = sbn.getNotification();
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
final String notificationKey = sbn.getKey();
boolean isActivityIntent = intent.isActivity();
final boolean afterKeyguardGone = isActivityIntent
&& PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
final boolean wasOccluded = mShadeController.isOccluded();
boolean showOverLockscreen = mKeyguardMonitor.isShowing()
&& PreviewInflater.wouldShowOverLockscreen(mContext,
intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
() -> handleNotificationClickAfterKeyguardDismissed(
sbn, row, controller, intent, notificationKey,
isActivityIntent, wasOccluded, showOverLockscreen);
if (showOverLockscreen) {
mIsCollapsingToShowActivityOverLockscreen = true;
postKeyguardAction.onDismiss();
} else {
mActivityStarter.dismissKeyguardThenExecute(
postKeyguardAction, null /* cancel */, afterKeyguardGone);
}
}
private boolean handleNotificationClickAfterKeyguardDismissed(
StatusBarNotification sbn,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
String notificationKey,
boolean isActivityIntent,
boolean wasOccluded,
boolean showOverLockscreen) {
// TODO: Some of this code may be able to move to NotificationEntryManager.
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(notificationKey)) {
// Release the HUN notification to the shade.
if (mPresenter.isPresenterFullyCollapsed()) {
HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
}
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
mHeadsUpManager.removeNotification(sbn.getKey(),
true /* releaseImmediately */);
}
StatusBarNotification parentToCancel = null;
if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
StatusBarNotification summarySbn =
mGroupManager.getLogicalGroupSummary(sbn).notification;
if (shouldAutoCancel(summarySbn)) {
parentToCancel = summarySbn;
}
}
final StatusBarNotification parentToCancelFinal = parentToCancel;
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
sbn, row, controller, intent, notificationKey,
isActivityIntent, wasOccluded, parentToCancelFinal);
if (showOverLockscreen) {
mShadeController.addPostCollapseAction(runnable);
mShadeController.collapsePanel(true /* animate */);
} else if (mKeyguardMonitor.isShowing()
&& mShadeController.isOccluded()) {
mShadeController.addAfterKeyguardGoneRunnable(runnable);
mShadeController.collapsePanel();
} else {
new Thread(runnable).start();
}
return !mNotificationPanel.isFullyCollapsed();
}
private void handleNotificationClickAfterPanelCollapsed(
StatusBarNotification sbn,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
String notificationKey,
boolean isActivityIntent,
boolean wasOccluded,
StatusBarNotification parentToCancelFinal) {
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
// point, so make sure new activity switches are now allowed.
ActivityManager.getService().resumeAppSwitches();
} catch (RemoteException e) {
}
int launchResult;
// If we are launching a work activity and require to launch
// separate work challenge, we defer the activity action and cancel
// notification until work challenge is unlocked.
if (isActivityIntent) {
final int userId = intent.getCreatorUserHandle().getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
// TODO(b/28935539): should allow certain activities to
// bypass work challenge
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
intent.getIntentSender(), notificationKey)) {
// Show work challenge, do not run PendingIntent and
// remove notification
collapseOnMainThread();
return;
}
}
}
Intent fillInIntent = null;
NotificationData.Entry entry = row.getEntry();
CharSequence remoteInputText = null;
if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
}
if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.key)) {
fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
remoteInputText.toString());
}
RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
row, wasOccluded);
try {
if (adapter != null) {
ActivityTaskManager.getService()
.registerRemoteAnimationForNextActivityStart(
intent.getCreatorPackage(), adapter);
}
launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, getActivityOptions(adapter));
mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
} catch (RemoteException | PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
Log.w(TAG, "Sending contentIntent failed: " + e);
// TODO: Dismiss Keyguard.
}
if (isActivityIntent) {
mAssistManager.hideAssist();
}
if (shouldCollapse()) {
collapseOnMainThread();
}
final int count =
mEntryManager.getNotificationData().getActiveNotifications().size();
final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
rank, count, true);
try {
mBarService.onNotificationClick(notificationKey, nv);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
if (parentToCancelFinal != null) {
removeNotification(parentToCancelFinal);
}
if (shouldAutoCancel(sbn)
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
notificationKey)) {
// Automatically remove all notifications that we may have kept around longer
removeNotification(sbn);
}
mIsCollapsingToShowActivityOverLockscreen = false;
}
@Override
public void startNotificationGutsIntent(final Intent intent, final int appUid,
ExpandableNotificationRow row) {
mActivityStarter.dismissKeyguardThenExecute(() -> {
AsyncTask.execute(() -> {
int launchResult = TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
mActivityLaunchAnimator.getLaunchAnimation(
row, mShadeController.isOccluded())),
new UserHandle(UserHandle.getUserId(appUid)));
mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
if (shouldCollapse()) {
// Putting it back on the main thread, since we're touching views
Dependency.get(MAIN_HANDLER).post(() -> mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
}
});
return true;
}, null, false /* afterKeyguardGone */);
}
@Override
public boolean isCollapsingToShowActivityOverLockscreen() {
return mIsCollapsingToShowActivityOverLockscreen;
}
private static boolean shouldAutoCancel(StatusBarNotification sbn) {
int flags = sbn.getNotification().flags;
if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
return false;
}
if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
return false;
}
return true;
}
private void collapseOnMainThread() {
if (Looper.getMainLooper().isCurrentThread()) {
mShadeController.collapsePanel();
} else {
Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel);
}
}
private boolean shouldCollapse() {
return mStatusBarStateController.getState() != StatusBarState.SHADE
|| !mActivityLaunchAnimator.isAnimationPending();
}
private void removeNotification(StatusBarNotification notification) {
// We have to post it to the UI thread for synchronization
Dependency.get(MAIN_HANDLER).post(() -> {
Runnable removeRunnable =
() -> mEntryManager.performRemoveNotification(notification);
if (mPresenter.isCollapsing()) {
// To avoid lags we're only performing the remove
// after the shade was collapsed
mShadeController.addPostCollapseAction(removeRunnable);
} else {
removeRunnable.run();
}
});
}
}

View File

@@ -14,35 +14,22 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.RemoteAnimationAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
@@ -50,13 +37,10 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.AmbientPulseManager;
@@ -65,9 +49,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
@@ -80,9 +62,7 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.PreviewInflater;
public class StatusBarNotificationPresenter implements NotificationPresenter {
@@ -93,7 +73,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
private final NotificationViewHierarchyManager mViewHierarchyManager =
Dependency.get(NotificationViewHierarchyManager.class);
@@ -105,12 +84,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
Dependency.get(NotificationEntryManager.class);
private final NotificationMediaManager mMediaManager =
Dependency.get(NotificationMediaManager.class);
private final NotificationRemoteInputManager mRemoteInputManager =
Dependency.get(NotificationRemoteInputManager.class);
private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
(StatusBarRemoteInputCallback) Dependency.get(Callback.class);
protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
private final NotificationPanelView mNotificationPanel;
@@ -122,7 +95,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
private final CommandQueue mCommandQueue;
private final AccessibilityManager mAccessibilityManager;
private final LockPatternUtils mLockPatternUtils;
private final KeyguardManager mKeyguardManager;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final int mMaxAllowedKeyguardNotifications;
@@ -133,34 +105,32 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
protected boolean mVrMode;
private int mMaxKeyguardNotifications;
private boolean mIsCollapsingToShowActivityOverLockscreen;
public StatusBarNotificationPresenter(Context context, NotificationPanelView panel,
HeadsUpManagerPhone headsUp, StatusBarWindowView statusBarWindow,
ViewGroup stackScroller, DozeScrimController dozeScrimController,
public StatusBarNotificationPresenter(Context context,
NotificationPanelView panel,
HeadsUpManagerPhone headsUp,
StatusBarWindowView statusBarWindow,
ViewGroup stackScroller,
DozeScrimController dozeScrimController,
ScrimController scrimController,
ActivityLaunchAnimator.Callback launchAnimatorCallback) {
ActivityLaunchAnimator activityLaunchAnimator) {
mContext = context;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
mCommandQueue = getComponent(context, CommandQueue.class);
mAboveShelfObserver = new AboveShelfObserver(stackScroller);
mActivityLaunchAnimator = activityLaunchAnimator;
mAboveShelfObserver.setListener(statusBarWindow.findViewById(
R.id.notification_container_parent));
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mDozeScrimController = dozeScrimController;
mScrimController = scrimController;
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mLockPatternUtils = new LockPatternUtils(context);
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mMaxAllowedKeyguardNotifications = context.getResources().getInteger(
R.integer.keyguard_max_notification_count);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mActivityLaunchAnimator = new ActivityLaunchAnimator(statusBarWindow,
launchAnimatorCallback,
mNotificationPanel,
(NotificationListContainer) stackScroller);
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
@@ -176,10 +146,12 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
}
mRemoteInputManager.setUpWithPresenter(this,
NotificationRemoteInputManager remoteInputManager =
Dependency.get(NotificationRemoteInputManager.class);
remoteInputManager.setUpWithCallback(
Dependency.get(NotificationRemoteInputManager.Callback.class),
mNotificationPanel.createRemoteInputDelegate());
mRemoteInputManager.getController().addCallback(
remoteInputManager.getController().addCallback(
Dependency.get(StatusBarWindowController.class));
NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
@@ -203,11 +175,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
}
}
@Override
public ActivityLaunchAnimator getActivityLaunchAnimator() {
return mActivityLaunchAnimator;
}
@Override
public boolean isCollapsing() {
return mNotificationPanel.isCollapsing()
@@ -215,11 +182,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
|| mActivityLaunchAnimator.isAnimationRunning();
}
@Override
public boolean isCollapsingToShowActivityOverLockscreen() {
return mIsCollapsingToShowActivityOverLockscreen;
}
@Override
public void onPerformRemoveNotification(StatusBarNotification n) {
if (mNotificationPanel.hasPulsingNotifications() &&
@@ -376,201 +338,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
mMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation);
}
@Override
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
RemoteInputController controller = mRemoteInputManager.getController();
if (controller.isRemoteInputActive(row.getEntry())
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
// We have an active remote input typed and the user clicked on the notification.
// this was probably unintentional, so we're closing the edit text instead.
controller.closeRemoteInputs();
return;
}
Notification notification = sbn.getNotification();
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
final String notificationKey = sbn.getKey();
boolean isActivityIntent = intent.isActivity();
final boolean afterKeyguardGone = isActivityIntent
&& PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
final boolean wasOccluded = mShadeController.isOccluded();
boolean showOverLockscreen = mKeyguardMonitor.isShowing()
&& PreviewInflater.wouldShowOverLockscreen(mContext,
intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
OnDismissAction postKeyguardAction = () -> {
// TODO: Some of this code may be able to move to NotificationEntryManager.
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(notificationKey)) {
// Release the HUN notification to the shade.
if (isPresenterFullyCollapsed()) {
HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
}
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
mHeadsUpManager.removeNotification(sbn.getKey(),
true /* releaseImmediately */);
}
StatusBarNotification parentToCancel = null;
if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
StatusBarNotification summarySbn =
mGroupManager.getLogicalGroupSummary(sbn).notification;
if (shouldAutoCancel(summarySbn)) {
parentToCancel = summarySbn;
}
}
final StatusBarNotification parentToCancelFinal = parentToCancel;
final Runnable runnable = () -> {
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
// point, so make sure new activity switches are now allowed.
ActivityManager.getService().resumeAppSwitches();
} catch (RemoteException e) {
}
int launchResult = ActivityManager.START_CANCELED;
if (intent != null) {
// If we are launching a work activity and require to launch
// separate work challenge, we defer the activity action and cancel
// notification until work challenge is unlocked.
if (isActivityIntent) {
final int userId = intent.getCreatorUserHandle().getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
// TODO(b/28935539): should allow certain activities to
// bypass work challenge
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
intent.getIntentSender(), notificationKey)) {
// Show work challenge, do not run PendingIntent and
// remove notification
collapseOnMainThread();
return;
}
}
}
Intent fillInIntent = null;
Entry entry = row.getEntry();
CharSequence remoteInputText = null;
if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
}
if (!TextUtils.isEmpty(remoteInputText)
&& !controller.isSpinning(entry.key)) {
fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
remoteInputText.toString());
}
RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
row, wasOccluded);
try {
if (adapter != null) {
ActivityTaskManager.getService()
.registerRemoteAnimationForNextActivityStart(
intent.getCreatorPackage(), adapter);
}
launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, getActivityOptions(adapter));
mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
} catch (RemoteException | PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
Log.w(TAG, "Sending contentIntent failed: " + e);
// TODO: Dismiss Keyguard.
}
if (isActivityIntent) {
mAssistManager.hideAssist();
}
}
if (shouldCollapse()) {
collapseOnMainThread();
}
final int count =
mEntryManager.getNotificationData().getActiveNotifications().size();
final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
rank, count, true);
try {
mBarService.onNotificationClick(notificationKey, nv);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
if (parentToCancelFinal != null) {
removeNotification(parentToCancelFinal);
}
if (shouldAutoCancel(sbn)
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
notificationKey)) {
// Automatically remove all notifications that we may have kept around longer
removeNotification(sbn);
}
mIsCollapsingToShowActivityOverLockscreen = false;
};
if (showOverLockscreen) {
mShadeController.addPostCollapseAction(runnable);
mShadeController.collapsePanel(true /* animate */);
} else if (mKeyguardMonitor.isShowing()
&& mShadeController.isOccluded()) {
mShadeController.addAfterKeyguardGoneRunnable(runnable);
mShadeController.collapsePanel();
} else {
new Thread(runnable).start();
}
return !mNotificationPanel.isFullyCollapsed();
};
if (showOverLockscreen) {
mIsCollapsingToShowActivityOverLockscreen = true;
postKeyguardAction.onDismiss();
} else {
mActivityStarter.dismissKeyguardThenExecute(
postKeyguardAction, null /* cancel */, afterKeyguardGone);
}
}
private void removeNotification(StatusBarNotification notification) {
// We have to post it to the UI thread for synchronization
Dependency.get(MAIN_HANDLER).post(() -> {
Runnable removeRunnable =
() -> mEntryManager.performRemoveNotification(notification);
if (isCollapsing()) {
// To avoid lags we're only performing the remove
// after the shade was collapsed
mShadeController.addPostCollapseAction(removeRunnable);
} else {
removeRunnable.run();
}
});
}
@Override
public void startNotificationGutsIntent(final Intent intent, final int appUid,
ExpandableNotificationRow row) {
mActivityStarter.dismissKeyguardThenExecute(() -> {
AsyncTask.execute(() -> {
int launchResult = TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
mActivityLaunchAnimator.getLaunchAnimation(
row, mShadeController.isOccluded())),
new UserHandle(UserHandle.getUserId(appUid)));
mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
if (shouldCollapse()) {
// Putting it back on the main thread, since we're touching views
Dependency.get(MAIN_HANDLER).post(() -> mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
}
});
return true;
}, null, false /* afterKeyguardGone */);
}
@Override
public int getMaxNotificationsWhileLocked(boolean recompute) {
if (recompute) {
@@ -600,41 +367,12 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
return mVrMode;
}
@Override
public boolean isPresenterLocked() {
return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
}
private void collapseOnMainThread() {
if (Looper.getMainLooper().isCurrentThread()) {
mShadeController.collapsePanel();
} else {
Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel);
}
}
private boolean shouldCollapse() {
return mStatusBarStateController.getState() != StatusBarState.SHADE
|| !mActivityLaunchAnimator.isAnimationPending();
}
private void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
mActivityStarter.dismissKeyguardThenExecute(dismissAction, null,
true /* afterKeyguardGone */);
}
private static boolean shouldAutoCancel(StatusBarNotification sbn) {
int flags = sbn.getNotification().flags;
if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
return false;
}
if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
return false;
}
return true;
}
private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
@Override
public void onVrStateChanged(boolean enabled) {
@@ -645,7 +383,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter {
private final CheckSaveListener mCheckSaveListener = new CheckSaveListener() {
@Override
public void checkSave(Runnable saveImportance, StatusBarNotification sbn) {
int state = mStatusBarStateController.getState();
// If the user has security enabled, show challenge if the setting is changed.
if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
&& mKeyguardManager.isKeyguardLocked()) {

View File

@@ -17,8 +17,7 @@ package com.android.systemui.statusbar.phone;
import static android.content.Intent.ACTION_DEVICE_LOCKED_CHANGED;
import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager
.NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
import android.app.ActivityManager;
import android.app.KeyguardManager;
@@ -163,7 +162,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks {
mPendingWorkRemoteInputView = clicked;
}
protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
// Clear pending remote view, as we do not want to trigger pending remote input view when
// it's called by other code

View File

@@ -91,7 +91,7 @@ public class NonPhoneDependencyTest extends SysuiTestCase {
mCheckSaveListener, mOnSettingsClickListener);
notificationLogger.setUpWithContainer(mListContainer);
mediaManager.setUpWithPresenter(mPresenter);
remoteInputManager.setUpWithPresenter(mPresenter, mRemoteInputManagerCallback,
remoteInputManager.setUpWithCallback(mRemoteInputManagerCallback,
mDelegate);
lockscreenUserManager.setUpWithPresenter(mPresenter);
viewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);

View File

@@ -1,8 +1,8 @@
package com.android.systemui.statusbar;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -22,13 +22,12 @@ import android.testing.TestableLooper;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputActiveExtender;
import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender;
import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyHistoryExtender;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.google.android.collect.Sets;
@@ -80,7 +79,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
mEntry = new NotificationData.Entry(mSbn);
mEntry.setRow(mRow);
mRemoteInputManager.setUpWithPresenterForTest(mPresenter, mCallback,
mRemoteInputManager.setUpWithPresenterForTest(mCallback,
mDelegate, mController);
for (NotificationLifetimeExtender extender : mRemoteInputManager.getLifetimeExtenders()) {
extender.setCallback(
@@ -201,11 +200,10 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
super(context);
}
public void setUpWithPresenterForTest(NotificationPresenter presenter,
Callback callback,
public void setUpWithPresenterForTest(Callback callback,
RemoteInputController.Delegate delegate,
RemoteInputController controller) {
super.setUpWithPresenter(presenter, callback, delegate);
super.setUpWithCallback(callback, delegate);
mRemoteInputController = controller;
}

View File

@@ -76,7 +76,7 @@ public class SmartReplyControllerTest extends SysuiTestCase {
mSmartReplyController);
mRemoteInputManager = new NotificationRemoteInputManager(mContext);
mRemoteInputManager.setUpWithPresenter(mPresenter, mCallback, mDelegate);
mRemoteInputManager.setUpWithCallback(mCallback, mDelegate);
mNotification = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")

View File

@@ -59,8 +59,8 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -92,7 +92,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Rule public MockitoRule mockito = MockitoJUnit.rule();
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationActivityStarter mNotificationActivityStarter;
@Mock private NotificationStackScrollLayout mStackScroller;
@Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@@ -110,6 +110,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mGutsManager = new NotificationGutsManager(mContext);
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
mCheckSaveListener, mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
}
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -217,7 +218,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_CAMERA);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
}
@@ -227,7 +229,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_RECORD_AUDIO);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
}
@@ -238,7 +241,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_RECORD_AUDIO);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction());
}
@@ -248,7 +252,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_SYSTEM_ALERT_WINDOW);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, captor.getValue().getAction());
}
@@ -260,7 +265,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_SYSTEM_ALERT_WINDOW);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
}
@@ -271,7 +277,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_SYSTEM_ALERT_WINDOW);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
}
@@ -282,7 +289,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
ops.add(OP_SYSTEM_ALERT_WINDOW);
mGutsManager.startAppOpsSettingsActivity("", 0, ops, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mPresenter, times(1)).startNotificationGutsIntent(captor.capture(), anyInt(), any());
verify(mNotificationActivityStarter, times(1))
.startNotificationGutsIntent(captor.capture(), anyInt(), any());
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
}

View File

@@ -70,7 +70,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
statusBarWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.Callback.class));
mock(ActivityLaunchAnimator.class));
}
@Test