Inline notif pipeline flag in NotifEntryManager
This change is a no-op; the flag is now enabled-by-default, so all removed code paths here are effectively dead. Bug: 200269355 Test: atest SystemUITests Change-Id: I6a04d1c238ea938a60cc2bb1f28d780480ad67fd Merged-In: I6a04d1c238ea938a60cc2bb1f28d780480ad67fd
This commit is contained in:
@@ -81,7 +81,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.SmartReplyController;
|
||||
import com.android.systemui.statusbar.VibratorHelper;
|
||||
import com.android.systemui.statusbar.events.PrivacyDotViewController;
|
||||
@@ -323,7 +322,6 @@ public class Dependency {
|
||||
@Inject Lazy<SmartReplyConstants> mSmartReplyConstants;
|
||||
@Inject Lazy<NotificationListener> mNotificationListener;
|
||||
@Inject Lazy<NotificationLogger> mNotificationLogger;
|
||||
@Inject Lazy<NotificationViewHierarchyManager> mNotificationViewHierarchyManager;
|
||||
@Inject Lazy<NotificationFilter> mNotificationFilter;
|
||||
@Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
|
||||
@Inject Lazy<SmartReplyController> mSmartReplyController;
|
||||
@@ -540,8 +538,6 @@ public class Dependency {
|
||||
mProviders.put(SmartReplyConstants.class, mSmartReplyConstants::get);
|
||||
mProviders.put(NotificationListener.class, mNotificationListener::get);
|
||||
mProviders.put(NotificationLogger.class, mNotificationLogger::get);
|
||||
mProviders.put(NotificationViewHierarchyManager.class,
|
||||
mNotificationViewHierarchyManager::get);
|
||||
mProviders.put(NotificationFilter.class, mNotificationFilter::get);
|
||||
mProviders.put(KeyguardDismissUtil.class, mKeyguardDismissUtil::get);
|
||||
mProviders.put(SmartReplyController.class, mSmartReplyController::get);
|
||||
|
||||
@@ -49,16 +49,6 @@ public interface NotificationPresenter extends ExpandableNotificationRow.OnExpan
|
||||
*/
|
||||
boolean isDeviceInVrMode();
|
||||
|
||||
/**
|
||||
* Updates the visual representation of the notifications.
|
||||
*/
|
||||
void updateNotificationViews(String reason);
|
||||
|
||||
/**
|
||||
* Called when the row states are updated by {@link NotificationViewHierarchyManager}.
|
||||
*/
|
||||
void onUpdateRowStates();
|
||||
|
||||
/**
|
||||
* @return true if the shade is collapsing.
|
||||
*/
|
||||
|
||||
@@ -1,631 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.dagger.CentralSurfacesModule;
|
||||
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
|
||||
import com.android.systemui.statusbar.notification.DynamicChildBindController;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifStats;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.Assert;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* NotificationViewHierarchyManager manages updating the view hierarchy of notification views based
|
||||
* on their group structure. For example, if a notification becomes bundled with another,
|
||||
* NotificationViewHierarchyManager will update the view hierarchy to reflect that. It also will
|
||||
* tell NotificationListContainer which notifications to display, and inform it of changes to those
|
||||
* notifications that might affect their display.
|
||||
*/
|
||||
public class NotificationViewHierarchyManager implements DynamicPrivacyController.Listener {
|
||||
private static final String TAG = "NotificationViewHierarchyManager";
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
/**
|
||||
* Re-usable map of top-level notifications to their sorted children if any.
|
||||
* If the top-level notification doesn't have children, its key will still exist in this map
|
||||
* with its value explicitly set to null.
|
||||
*/
|
||||
private final HashMap<NotificationEntry, List<NotificationEntry>> mTmpChildOrderMap =
|
||||
new HashMap<>();
|
||||
|
||||
// Dependencies:
|
||||
private final DynamicChildBindController mDynamicChildBindController;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
protected final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
protected final NotificationGroupManagerLegacy mGroupManager;
|
||||
protected final VisualStabilityManager mVisualStabilityManager;
|
||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||
private final NotificationEntryManager mEntryManager;
|
||||
private final LowPriorityInflationHelper mLowPriorityInflationHelper;
|
||||
|
||||
/**
|
||||
* {@code true} if notifications not part of a group should by default be rendered in their
|
||||
* expanded state. If {@code false}, then only the first notification will be expanded if
|
||||
* possible.
|
||||
*/
|
||||
private final boolean mAlwaysExpandNonGroupedNotification;
|
||||
private final Optional<Bubbles> mBubblesOptional;
|
||||
private final DynamicPrivacyController mDynamicPrivacyController;
|
||||
private final KeyguardBypassController mBypassController;
|
||||
private final NotifPipelineFlags mNotifPipelineFlags;
|
||||
private AssistantFeedbackController mAssistantFeedbackController;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final Context mContext;
|
||||
|
||||
private NotificationPresenter mPresenter;
|
||||
private NotifStackController mStackController;
|
||||
private NotificationListContainer mListContainer;
|
||||
|
||||
// Used to help track down re-entrant calls to our update methods, which will cause bugs.
|
||||
private boolean mPerformingUpdate;
|
||||
// Hack to get around re-entrant call in onDynamicPrivacyChanged() until we can track down
|
||||
// the problem.
|
||||
private boolean mIsHandleDynamicPrivacyChangeScheduled;
|
||||
|
||||
/**
|
||||
* Injected constructor. See {@link CentralSurfacesModule}.
|
||||
*/
|
||||
public NotificationViewHierarchyManager(
|
||||
Context context,
|
||||
@Main Handler mainHandler,
|
||||
FeatureFlags featureFlags,
|
||||
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
VisualStabilityManager visualStabilityManager,
|
||||
StatusBarStateController statusBarStateController,
|
||||
NotificationEntryManager notificationEntryManager,
|
||||
KeyguardBypassController bypassController,
|
||||
Optional<Bubbles> bubblesOptional,
|
||||
DynamicPrivacyController privacyController,
|
||||
DynamicChildBindController dynamicChildBindController,
|
||||
LowPriorityInflationHelper lowPriorityInflationHelper,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
KeyguardStateController keyguardStateController) {
|
||||
mContext = context;
|
||||
mHandler = mainHandler;
|
||||
mFeatureFlags = featureFlags;
|
||||
mLockscreenUserManager = notificationLockscreenUserManager;
|
||||
mBypassController = bypassController;
|
||||
mGroupManager = groupManager;
|
||||
mVisualStabilityManager = visualStabilityManager;
|
||||
mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
|
||||
mEntryManager = notificationEntryManager;
|
||||
mNotifPipelineFlags = notifPipelineFlags;
|
||||
Resources res = context.getResources();
|
||||
mAlwaysExpandNonGroupedNotification =
|
||||
res.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications);
|
||||
mBubblesOptional = bubblesOptional;
|
||||
mDynamicPrivacyController = privacyController;
|
||||
mDynamicChildBindController = dynamicChildBindController;
|
||||
mLowPriorityInflationHelper = lowPriorityInflationHelper;
|
||||
mAssistantFeedbackController = assistantFeedbackController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter,
|
||||
NotifStackController stackController,
|
||||
NotificationListContainer listContainer) {
|
||||
mPresenter = presenter;
|
||||
mStackController = stackController;
|
||||
mListContainer = listContainer;
|
||||
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mDynamicPrivacyController.addListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the visual representation of the notifications.
|
||||
*/
|
||||
//TODO: Rewrite this to focus on Entries, or some other data object instead of views
|
||||
public void updateNotificationViews() {
|
||||
Assert.isMainThread();
|
||||
if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
|
||||
return;
|
||||
}
|
||||
Trace.beginSection("NotificationViewHierarchyManager.updateNotificationViews");
|
||||
|
||||
beginUpdate();
|
||||
|
||||
boolean dynamicallyUnlocked = mDynamicPrivacyController.isDynamicallyUnlocked()
|
||||
&& !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
|
||||
&& mKeyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
|
||||
KeyguardUpdateMonitor.getCurrentUser()))
|
||||
&& !mKeyguardStateController.isKeyguardGoingAway();
|
||||
List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
|
||||
ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
|
||||
final int N = activeNotifications.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
NotificationEntry ent = activeNotifications.get(i);
|
||||
if (shouldSuppressActiveNotification(ent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int userId = ent.getSbn().getUserId();
|
||||
|
||||
// Display public version of the notification if we need to redact.
|
||||
// TODO: This area uses a lot of calls into NotificationLockscreenUserManager.
|
||||
// We can probably move some of this code there.
|
||||
int currentUserId = mLockscreenUserManager.getCurrentUserId();
|
||||
boolean devicePublic = mLockscreenUserManager.isLockscreenPublicMode(currentUserId);
|
||||
boolean userPublic = devicePublic
|
||||
|| mLockscreenUserManager.isLockscreenPublicMode(userId);
|
||||
if (userPublic && dynamicallyUnlocked
|
||||
&& (userId == currentUserId || userId == UserHandle.USER_ALL
|
||||
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
|
||||
userPublic = false;
|
||||
}
|
||||
boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent);
|
||||
boolean sensitive = userPublic && needsRedaction;
|
||||
boolean deviceSensitive = devicePublic
|
||||
&& !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
|
||||
currentUserId);
|
||||
ent.setSensitive(sensitive, deviceSensitive);
|
||||
ent.getRow().setNeedsRedaction(needsRedaction);
|
||||
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
|
||||
boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
|
||||
|
||||
boolean groupChangesAllowed =
|
||||
mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs
|
||||
|| !ent.hasFinishedInitialization(); // notif recently added
|
||||
|
||||
NotificationEntry parent = mGroupManager.getGroupSummary(ent);
|
||||
if (!groupChangesAllowed) {
|
||||
// We don't to change groups while the user is looking at them
|
||||
boolean wasChildInGroup = ent.isChildInGroup();
|
||||
if (isChildInGroup && !wasChildInGroup) {
|
||||
isChildInGroup = wasChildInGroup;
|
||||
mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager,
|
||||
false /* persistent */);
|
||||
} else if (!isChildInGroup && wasChildInGroup) {
|
||||
// We allow grouping changes if the group was collapsed
|
||||
if (mGroupManager.isLogicalGroupExpanded(ent.getSbn())) {
|
||||
isChildInGroup = wasChildInGroup;
|
||||
parent = ent.getRow().getNotificationParent().getEntry();
|
||||
mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager,
|
||||
false /* persistent */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isChildInGroup) {
|
||||
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent);
|
||||
if (orderedChildren == null) {
|
||||
orderedChildren = new ArrayList<>();
|
||||
mTmpChildOrderMap.put(parent, orderedChildren);
|
||||
}
|
||||
orderedChildren.add(ent);
|
||||
} else {
|
||||
// Top-level notif (either a summary or single notification)
|
||||
|
||||
// A child may have already added its summary to mTmpChildOrderMap with a
|
||||
// list of children. This can happen since there's no guarantee summaries are
|
||||
// sorted before its children.
|
||||
if (!mTmpChildOrderMap.containsKey(ent)) {
|
||||
// mTmpChildOrderMap's keyset is used to iterate through all entries, so it's
|
||||
// necessary to add each top-level notif as a key
|
||||
mTmpChildOrderMap.put(ent, null);
|
||||
}
|
||||
toShow.add(ent.getRow());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>();
|
||||
for (int i=0; i< mListContainer.getContainerChildCount(); i++) {
|
||||
View child = mListContainer.getContainerChildAt(i);
|
||||
if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
|
||||
// Blocking helper is effectively a detached view. Don't bother removing it from the
|
||||
// layout.
|
||||
if (!row.isBlockingHelperShowing()) {
|
||||
viewsToRemove.add((ExpandableNotificationRow) child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
|
||||
NotificationEntry entry = viewToRemove.getEntry();
|
||||
if (mEntryManager.getPendingOrActiveNotif(entry.getKey()) != null
|
||||
&& !shouldSuppressActiveNotification(entry)) {
|
||||
// we are only transferring this notification to its parent, don't generate an
|
||||
// animation. If the notification is suppressed, this isn't a transfer.
|
||||
mListContainer.setChildTransferInProgress(true);
|
||||
}
|
||||
if (viewToRemove.isSummaryWithChildren()) {
|
||||
viewToRemove.removeAllChildren();
|
||||
}
|
||||
mListContainer.removeContainerView(viewToRemove);
|
||||
mListContainer.setChildTransferInProgress(false);
|
||||
}
|
||||
|
||||
removeNotificationChildren();
|
||||
|
||||
for (int i = 0; i < toShow.size(); i++) {
|
||||
View v = toShow.get(i);
|
||||
if (v.getParent() == null) {
|
||||
mVisualStabilityManager.notifyViewAddition(v);
|
||||
mListContainer.addContainerView(v);
|
||||
} else if (!mListContainer.containsView(v)) {
|
||||
// the view is added somewhere else. Let's make sure
|
||||
// the ordering works properly below, by excluding these
|
||||
toShow.remove(v);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
addNotificationChildrenAndSort();
|
||||
|
||||
// So after all this work notifications still aren't sorted correctly.
|
||||
// Let's do that now by advancing through toShow and mListContainer in
|
||||
// lock-step, making sure mListContainer matches what we see in toShow.
|
||||
int j = 0;
|
||||
for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
|
||||
View child = mListContainer.getContainerChildAt(i);
|
||||
if (!(child instanceof ExpandableNotificationRow)) {
|
||||
// We don't care about non-notification views.
|
||||
continue;
|
||||
}
|
||||
if (((ExpandableNotificationRow) child).isBlockingHelperShowing()) {
|
||||
// Don't count/reorder notifications that are showing the blocking helper!
|
||||
continue;
|
||||
}
|
||||
|
||||
ExpandableNotificationRow targetChild = toShow.get(j);
|
||||
if (child != targetChild) {
|
||||
// Oops, wrong notification at this position. Put the right one
|
||||
// here and advance both lists.
|
||||
if (mVisualStabilityManager.canReorderNotification(targetChild)) {
|
||||
mListContainer.changeViewPosition(targetChild, i);
|
||||
} else {
|
||||
mVisualStabilityManager.addReorderingAllowedCallback(mEntryManager,
|
||||
false /* persistent */);
|
||||
}
|
||||
}
|
||||
j++;
|
||||
|
||||
}
|
||||
|
||||
mDynamicChildBindController.updateContentViews(mTmpChildOrderMap);
|
||||
mVisualStabilityManager.onReorderingFinished();
|
||||
// clear the map again for the next usage
|
||||
mTmpChildOrderMap.clear();
|
||||
|
||||
updateRowStatesInternal();
|
||||
updateNotifStats();
|
||||
|
||||
mListContainer.onNotificationViewUpdateFinished();
|
||||
|
||||
endUpdate();
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
/**
|
||||
* In the spirit of unidirectional data flow, calculate this information when the notification
|
||||
* views are updated, and set it once, speeding up lookups later.
|
||||
* This is analogous to logic in the
|
||||
* {@link com.android.systemui.statusbar.notification.collection.coordinator.StackCoordinator}
|
||||
*/
|
||||
private void updateNotifStats() {
|
||||
Trace.beginSection("NotificationViewHierarchyManager.updateNotifStats");
|
||||
boolean hasNonClearableAlertingNotifs = false;
|
||||
boolean hasClearableAlertingNotifs = false;
|
||||
boolean hasNonClearableSilentNotifs = false;
|
||||
boolean hasClearableSilentNotifs = false;
|
||||
final int childCount = mListContainer.getContainerChildCount();
|
||||
int visibleTopLevelEntries = 0;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = mListContainer.getContainerChildAt(i);
|
||||
if (child == null || child.getVisibility() == View.GONE) {
|
||||
continue;
|
||||
}
|
||||
if (!(child instanceof ExpandableNotificationRow)) {
|
||||
continue;
|
||||
}
|
||||
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT;
|
||||
// NOTE: NotificationEntry.isClearable() will internally check group children to ensure
|
||||
// the group itself definitively clearable.
|
||||
boolean isClearable = row.getEntry().isClearable();
|
||||
visibleTopLevelEntries++;
|
||||
if (isSilent) {
|
||||
if (isClearable) {
|
||||
hasClearableSilentNotifs = true;
|
||||
} else { // !isClearable
|
||||
hasNonClearableSilentNotifs = true;
|
||||
}
|
||||
} else { // !isSilent
|
||||
if (isClearable) {
|
||||
hasClearableAlertingNotifs = true;
|
||||
} else { // !isClearable
|
||||
hasNonClearableAlertingNotifs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
mStackController.setNotifStats(new NotifStats(
|
||||
visibleTopLevelEntries /* numActiveNotifs */,
|
||||
hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */,
|
||||
hasClearableAlertingNotifs /* hasClearableAlertingNotifs */,
|
||||
hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */,
|
||||
hasClearableSilentNotifs /* hasClearableSilentNotifs */
|
||||
));
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should a notification entry from the active list be suppressed and not show?
|
||||
*/
|
||||
private boolean shouldSuppressActiveNotification(NotificationEntry ent) {
|
||||
final boolean isBubbleNotificationSuppressedFromShade = mBubblesOptional.isPresent()
|
||||
&& mBubblesOptional.get().isBubbleNotificationSuppressedFromShade(
|
||||
ent.getKey(), ent.getSbn().getGroupKey());
|
||||
if (ent.isRowDismissed() || ent.isRowRemoved()
|
||||
|| isBubbleNotificationSuppressedFromShade) {
|
||||
// we want to suppress removed notifications because they could
|
||||
// temporarily become children if they were isolated before.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addNotificationChildrenAndSort() {
|
||||
// Let's now add all notification children which are missing
|
||||
boolean orderChanged = false;
|
||||
ArrayList<ExpandableNotificationRow> orderedRows = new ArrayList<>();
|
||||
for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
|
||||
View view = mListContainer.getContainerChildAt(i);
|
||||
if (!(view instanceof ExpandableNotificationRow)) {
|
||||
// We don't care about non-notification views.
|
||||
continue;
|
||||
}
|
||||
|
||||
ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
|
||||
List<ExpandableNotificationRow> children = parent.getAttachedChildren();
|
||||
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry());
|
||||
if (orderedChildren == null) {
|
||||
// Not a group
|
||||
continue;
|
||||
}
|
||||
parent.setUntruncatedChildCount(orderedChildren.size());
|
||||
for (int childIndex = 0; childIndex < orderedChildren.size(); childIndex++) {
|
||||
ExpandableNotificationRow childView = orderedChildren.get(childIndex).getRow();
|
||||
if (children == null || !children.contains(childView)) {
|
||||
if (childView.getParent() != null) {
|
||||
Log.wtf(TAG, "trying to add a notification child that already has "
|
||||
+ "a parent. class:" + childView.getParent().getClass()
|
||||
+ "\n child: " + childView);
|
||||
// This shouldn't happen. We can recover by removing it though.
|
||||
((ViewGroup) childView.getParent()).removeView(childView);
|
||||
}
|
||||
mVisualStabilityManager.notifyViewAddition(childView);
|
||||
parent.addChildNotification(childView, childIndex);
|
||||
mListContainer.notifyGroupChildAdded(childView);
|
||||
}
|
||||
orderedRows.add(childView);
|
||||
}
|
||||
|
||||
// Finally after removing and adding has been performed we can apply the order.
|
||||
orderChanged |= parent.applyChildOrder(orderedRows, mVisualStabilityManager,
|
||||
mEntryManager);
|
||||
orderedRows.clear();
|
||||
}
|
||||
if (orderChanged) {
|
||||
mListContainer.generateChildOrderChangedEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNotificationChildren() {
|
||||
// First let's remove all children which don't belong in the parents
|
||||
ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
|
||||
for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
|
||||
View view = mListContainer.getContainerChildAt(i);
|
||||
if (!(view instanceof ExpandableNotificationRow)) {
|
||||
// We don't care about non-notification views.
|
||||
continue;
|
||||
}
|
||||
|
||||
ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
|
||||
List<ExpandableNotificationRow> children = parent.getAttachedChildren();
|
||||
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry());
|
||||
|
||||
if (children != null) {
|
||||
toRemove.clear();
|
||||
for (ExpandableNotificationRow childRow : children) {
|
||||
if ((orderedChildren == null
|
||||
|| !orderedChildren.contains(childRow.getEntry()))
|
||||
&& !childRow.keepInParent()) {
|
||||
toRemove.add(childRow);
|
||||
}
|
||||
}
|
||||
for (ExpandableNotificationRow remove : toRemove) {
|
||||
parent.removeChildNotification(remove);
|
||||
if (mEntryManager.getActiveNotificationUnfiltered(
|
||||
remove.getEntry().getSbn().getKey()) == null) {
|
||||
// We only want to add an animation if the view is completely removed
|
||||
// otherwise it's just a transfer
|
||||
mListContainer.notifyGroupChildRemoved(remove,
|
||||
parent.getChildrenContainer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates expanded, dimmed and locked states of notification rows.
|
||||
*/
|
||||
public void updateRowStates() {
|
||||
Assert.isMainThread();
|
||||
if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginUpdate();
|
||||
updateRowStatesInternal();
|
||||
endUpdate();
|
||||
}
|
||||
|
||||
private void updateRowStatesInternal() {
|
||||
Trace.beginSection("NotificationViewHierarchyManager.updateRowStates");
|
||||
final int N = mListContainer.getContainerChildCount();
|
||||
|
||||
int visibleNotifications = 0;
|
||||
boolean onKeyguard =
|
||||
mStatusBarStateController.getCurrentOrUpcomingState() == StatusBarState.KEYGUARD;
|
||||
Stack<ExpandableNotificationRow> stack = new Stack<>();
|
||||
for (int i = N - 1; i >= 0; i--) {
|
||||
View child = mListContainer.getContainerChildAt(i);
|
||||
if (!(child instanceof ExpandableNotificationRow)) {
|
||||
continue;
|
||||
}
|
||||
stack.push((ExpandableNotificationRow) child);
|
||||
}
|
||||
while(!stack.isEmpty()) {
|
||||
ExpandableNotificationRow row = stack.pop();
|
||||
NotificationEntry entry = row.getEntry();
|
||||
boolean isChildNotification = mGroupManager.isChildInGroup(entry);
|
||||
|
||||
if (!onKeyguard) {
|
||||
// If mAlwaysExpandNonGroupedNotification is false, then only expand the
|
||||
// very first notification and if it's not a child of grouped notifications.
|
||||
row.setSystemExpanded(mAlwaysExpandNonGroupedNotification
|
||||
|| (visibleNotifications == 0 && !isChildNotification
|
||||
&& !row.isLowPriority()));
|
||||
}
|
||||
|
||||
int userId = entry.getSbn().getUserId();
|
||||
boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
|
||||
entry.getSbn()) && !entry.isRowRemoved();
|
||||
boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
|
||||
if (!showOnKeyguard) {
|
||||
// min priority notifications should show if their summary is showing
|
||||
if (mGroupManager.isChildInGroup(entry)) {
|
||||
NotificationEntry summary = mGroupManager.getLogicalGroupSummary(entry);
|
||||
if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
|
||||
showOnKeyguard = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (suppressedSummary
|
||||
|| mLockscreenUserManager.shouldHideNotifications(userId)
|
||||
|| (onKeyguard && !showOnKeyguard)) {
|
||||
entry.getRow().setVisibility(View.GONE);
|
||||
} else {
|
||||
boolean wasGone = entry.getRow().getVisibility() == View.GONE;
|
||||
if (wasGone) {
|
||||
entry.getRow().setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (!isChildNotification && !entry.getRow().isRemoved()) {
|
||||
if (wasGone) {
|
||||
// notify the scroller of a child addition
|
||||
mListContainer.generateAddAnimation(entry.getRow(),
|
||||
!showOnKeyguard /* fromMoreCard */);
|
||||
}
|
||||
visibleNotifications++;
|
||||
}
|
||||
}
|
||||
if (row.isSummaryWithChildren()) {
|
||||
List<ExpandableNotificationRow> notificationChildren =
|
||||
row.getAttachedChildren();
|
||||
int size = notificationChildren.size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
stack.push(notificationChildren.get(i));
|
||||
}
|
||||
}
|
||||
row.setFeedbackIcon(mAssistantFeedbackController.getFeedbackIcon(entry));
|
||||
row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs());
|
||||
}
|
||||
|
||||
Trace.beginSection("NotificationPresenter#onUpdateRowStates");
|
||||
mPresenter.onUpdateRowStates();
|
||||
Trace.endSection();
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDynamicPrivacyChanged() {
|
||||
mNotifPipelineFlags.assertLegacyPipelineEnabled();
|
||||
if (mPerformingUpdate) {
|
||||
Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
|
||||
}
|
||||
// This listener can be called from updateNotificationViews() via a convoluted listener
|
||||
// chain, so we post here to prevent a re-entrant call. See b/136186188
|
||||
// TODO: Refactor away the need for this
|
||||
if (!mIsHandleDynamicPrivacyChangeScheduled) {
|
||||
mIsHandleDynamicPrivacyChangeScheduled = true;
|
||||
mHandler.post(this::onHandleDynamicPrivacyChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandleDynamicPrivacyChanged() {
|
||||
mIsHandleDynamicPrivacyChangeScheduled = false;
|
||||
updateNotificationViews();
|
||||
}
|
||||
|
||||
private void beginUpdate() {
|
||||
if (mPerformingUpdate) {
|
||||
Log.wtf(TAG, "Re-entrant code during update", new Exception());
|
||||
}
|
||||
mPerformingUpdate = true;
|
||||
}
|
||||
|
||||
private void endUpdate() {
|
||||
if (!mPerformingUpdate) {
|
||||
Log.wtf(TAG, "Manager state has become desynced", new Exception());
|
||||
}
|
||||
mPerformingUpdate = false;
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,11 @@ import android.service.dreams.IDreamManager;
|
||||
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
@@ -42,23 +40,16 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.RemoteInputNotificationRebuilder;
|
||||
import com.android.systemui.statusbar.SmartReplyController;
|
||||
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry;
|
||||
import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler;
|
||||
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
|
||||
import com.android.systemui.statusbar.notification.DynamicChildBindController;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
@@ -73,13 +64,11 @@ import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.RemoteInputUriController;
|
||||
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -182,47 +171,6 @@ public interface CentralSurfacesDependenciesModule {
|
||||
NotificationRemoteInputManager.Callback provideNotificationRemoteInputManagerCallback(
|
||||
StatusBarRemoteInputCallback callbackImpl);
|
||||
|
||||
/** */
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static NotificationViewHierarchyManager provideNotificationViewHierarchyManager(
|
||||
Context context,
|
||||
@Main Handler mainHandler,
|
||||
FeatureFlags featureFlags,
|
||||
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
VisualStabilityManager visualStabilityManager,
|
||||
StatusBarStateController statusBarStateController,
|
||||
NotificationEntryManager notificationEntryManager,
|
||||
KeyguardBypassController bypassController,
|
||||
Optional<Bubbles> bubblesOptional,
|
||||
DynamicPrivacyController privacyController,
|
||||
DynamicChildBindController dynamicChildBindController,
|
||||
LowPriorityInflationHelper lowPriorityInflationHelper,
|
||||
AssistantFeedbackController assistantFeedbackController,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
KeyguardStateController keyguardStateController) {
|
||||
return new NotificationViewHierarchyManager(
|
||||
context,
|
||||
mainHandler,
|
||||
featureFlags,
|
||||
notificationLockscreenUserManager,
|
||||
groupManager,
|
||||
visualStabilityManager,
|
||||
statusBarStateController,
|
||||
notificationEntryManager,
|
||||
bypassController,
|
||||
bubblesOptional,
|
||||
privacyController,
|
||||
dynamicChildBindController,
|
||||
lowPriorityInflationHelper,
|
||||
assistantFeedbackController,
|
||||
notifPipelineFlags,
|
||||
keyguardUpdateMonitor,
|
||||
keyguardStateController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides our instance of CommandQueue which is considered optional.
|
||||
*/
|
||||
|
||||
@@ -29,10 +29,6 @@ class NotifPipelineFlags @Inject constructor(
|
||||
val featureFlags: FeatureFlags
|
||||
) {
|
||||
fun checkLegacyPipelineEnabled(): Boolean {
|
||||
if (!isNewPipelineEnabled()) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (Compile.IS_DEBUG) {
|
||||
Toast.makeText(context, "Old pipeline code running!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@@ -45,11 +41,6 @@ class NotifPipelineFlags @Inject constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
fun assertLegacyPipelineEnabled(): Unit =
|
||||
check(!isNewPipelineEnabled()) { "Old pipeline code running w/ new pipeline enabled" }
|
||||
|
||||
fun isNewPipelineEnabled(): Boolean = true
|
||||
|
||||
fun isDevLoggingEnabled(): Boolean =
|
||||
featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
|
||||
|
||||
|
||||
@@ -46,11 +46,9 @@ import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.statusbar.NotificationLifetimeExtender;
|
||||
import com.android.systemui.statusbar.NotificationListener;
|
||||
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
|
||||
import com.android.systemui.statusbar.NotificationUiAdjustment;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationRanker;
|
||||
@@ -113,7 +111,6 @@ public class NotificationEntryManager implements
|
||||
private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy;
|
||||
private final LeakDetector mLeakDetector;
|
||||
private final IStatusBarService mStatusBarService;
|
||||
private final NotifLiveDataStoreImpl mNotifLiveDataStore;
|
||||
private final DumpManager mDumpManager;
|
||||
private final Executor mBgExecutor;
|
||||
|
||||
@@ -141,7 +138,6 @@ public class NotificationEntryManager implements
|
||||
private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
|
||||
|
||||
private LegacyNotificationRanker mRanker = new LegacyNotificationRankerStub();
|
||||
private NotificationPresenter mPresenter;
|
||||
private RankingMap mLatestRankingMap;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -161,7 +157,6 @@ public class NotificationEntryManager implements
|
||||
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
|
||||
LeakDetector leakDetector,
|
||||
IStatusBarService statusBarService,
|
||||
NotifLiveDataStoreImpl notifLiveDataStore,
|
||||
DumpManager dumpManager,
|
||||
@Background Executor bgExecutor
|
||||
) {
|
||||
@@ -172,7 +167,6 @@ public class NotificationEntryManager implements
|
||||
mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
|
||||
mLeakDetector = leakDetector;
|
||||
mStatusBarService = statusBarService;
|
||||
mNotifLiveDataStore = notifLiveDataStore;
|
||||
mDumpManager = dumpManager;
|
||||
mBgExecutor = bgExecutor;
|
||||
}
|
||||
@@ -250,10 +244,6 @@ public class NotificationEntryManager implements
|
||||
mRemoveInterceptors.remove(interceptor);
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter) {
|
||||
mPresenter = presenter;
|
||||
}
|
||||
|
||||
/** Adds multiple {@link NotificationLifetimeExtender}s. */
|
||||
public void addNotificationLifetimeExtenders(List<NotificationLifetimeExtender> extenders) {
|
||||
for (NotificationLifetimeExtender extender : extenders) {
|
||||
@@ -663,11 +653,6 @@ public class NotificationEntryManager implements
|
||||
listener.onEntryBind(entry, notification);
|
||||
}
|
||||
|
||||
// Construct the expanded view.
|
||||
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mNotificationRowBinderLazy.get().inflateViews(entry, null, mInflationCallback);
|
||||
}
|
||||
|
||||
mPendingNotifications.put(key, entry);
|
||||
mLogger.logNotifAdded(entry.getKey());
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
@@ -724,10 +709,6 @@ public class NotificationEntryManager implements
|
||||
listener.onEntryUpdated(entry, fromSystem);
|
||||
}
|
||||
|
||||
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mNotificationRowBinderLazy.get().inflateViews(entry, null, mInflationCallback);
|
||||
}
|
||||
|
||||
updateNotifications("updateNotificationInternal");
|
||||
|
||||
for (NotificationEntryListener listener : mNotificationEntryListeners) {
|
||||
@@ -752,17 +733,7 @@ public class NotificationEntryManager implements
|
||||
* @param reason why the notifications are updating
|
||||
*/
|
||||
public void updateNotifications(String reason) {
|
||||
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mLogger.logUseWhileNewPipelineActive("updateNotifications", reason);
|
||||
return;
|
||||
}
|
||||
Trace.beginSection("NotificationEntryManager.updateNotifications");
|
||||
reapplyFilterAndSort(reason);
|
||||
if (mPresenter != null) {
|
||||
mPresenter.updateNotificationViews(reason);
|
||||
}
|
||||
mNotifLiveDataStore.setActiveNotifList(getVisibleNotifications());
|
||||
Trace.endSection();
|
||||
mLogger.logUseWhileNewPipelineActive("updateNotifications", reason);
|
||||
}
|
||||
|
||||
public void updateNotificationRanking(RankingMap rankingMap) {
|
||||
@@ -939,26 +910,12 @@ public class NotificationEntryManager implements
|
||||
|
||||
/** Resorts / filters the current notification set with the current RankingMap */
|
||||
public void reapplyFilterAndSort(String reason) {
|
||||
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mLogger.logUseWhileNewPipelineActive("reapplyFilterAndSort", reason);
|
||||
return;
|
||||
}
|
||||
Trace.beginSection("NotificationEntryManager.reapplyFilterAndSort");
|
||||
updateRankingAndSort(mRanker.getRankingMap(), reason);
|
||||
Trace.endSection();
|
||||
mLogger.logUseWhileNewPipelineActive("reapplyFilterAndSort", reason);
|
||||
}
|
||||
|
||||
/** Calls to NotificationRankingManager and updates mSortedAndFiltered */
|
||||
private void updateRankingAndSort(RankingMap rankingMap, String reason) {
|
||||
if (mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||
mLogger.logUseWhileNewPipelineActive("updateRankingAndSort", reason);
|
||||
return;
|
||||
}
|
||||
Trace.beginSection("NotificationEntryManager.updateRankingAndSort");
|
||||
mSortedAndFiltered.clear();
|
||||
mSortedAndFiltered.addAll(mRanker.updateRanking(
|
||||
rankingMap, mActiveNotifications.values(), reason));
|
||||
Trace.endSection();
|
||||
mLogger.logUseWhileNewPipelineActive("updateRankingAndSort", reason);
|
||||
}
|
||||
|
||||
/** dump the current active notification list. Called from CentralSurfaces */
|
||||
|
||||
@@ -127,7 +127,6 @@ public interface NotificationsModule {
|
||||
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
|
||||
LeakDetector leakDetector,
|
||||
IStatusBarService statusBarService,
|
||||
NotifLiveDataStoreImpl notifLiveDataStore,
|
||||
DumpManager dumpManager,
|
||||
@Background Executor bgExecutor) {
|
||||
return new NotificationEntryManager(
|
||||
@@ -138,7 +137,6 @@ public interface NotificationsModule {
|
||||
notificationRemoteInputManagerLazy,
|
||||
leakDetector,
|
||||
statusBarService,
|
||||
notifLiveDataStore,
|
||||
dumpManager,
|
||||
bgExecutor);
|
||||
}
|
||||
@@ -174,7 +172,6 @@ public interface NotificationsModule {
|
||||
accessibilityManager,
|
||||
highPriorityProvider,
|
||||
notificationManager,
|
||||
notificationEntryManager,
|
||||
peopleSpaceWidgetManager,
|
||||
launcherApps,
|
||||
shortcutManager,
|
||||
|
||||
@@ -37,7 +37,6 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
@@ -60,13 +59,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
||||
private final List<NotificationInterruptSuppressor> mSuppressors = new ArrayList<>();
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final NotificationFilter mNotificationFilter;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final PowerManager mPowerManager;
|
||||
private final IDreamManager mDreamManager;
|
||||
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
|
||||
private final BatteryController mBatteryController;
|
||||
private final ContentObserver mHeadsUpObserver;
|
||||
private final HeadsUpManager mHeadsUpManager;
|
||||
private final NotificationInterruptLogger mLogger;
|
||||
private final NotifPipelineFlags mFlags;
|
||||
@@ -81,7 +78,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
||||
PowerManager powerManager,
|
||||
IDreamManager dreamManager,
|
||||
AmbientDisplayConfiguration ambientDisplayConfiguration,
|
||||
NotificationFilter notificationFilter,
|
||||
BatteryController batteryController,
|
||||
StatusBarStateController statusBarStateController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
@@ -95,14 +91,13 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
||||
mDreamManager = dreamManager;
|
||||
mBatteryController = batteryController;
|
||||
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
|
||||
mNotificationFilter = notificationFilter;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mHeadsUpManager = headsUpManager;
|
||||
mLogger = logger;
|
||||
mFlags = flags;
|
||||
mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
|
||||
mHeadsUpObserver = new ContentObserver(mainHandler) {
|
||||
ContentObserver headsUpObserver = new ContentObserver(mainHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
boolean wasUsing = mUseHeadsUp;
|
||||
@@ -125,12 +120,12 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
||||
mContentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED),
|
||||
true,
|
||||
mHeadsUpObserver);
|
||||
headsUpObserver);
|
||||
mContentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
|
||||
mHeadsUpObserver);
|
||||
headsUpObserver);
|
||||
}
|
||||
mHeadsUpObserver.onChange(true); // set up
|
||||
headsUpObserver.onChange(true); // set up
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,6 @@ import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.app.NotificationChannel;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
@@ -63,13 +62,11 @@ import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
|
||||
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewListener;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
|
||||
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
@@ -114,7 +111,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
private NotificationPresenter mPresenter;
|
||||
private NotificationActivityStarter mNotificationActivityStarter;
|
||||
private NotificationListContainer mListContainer;
|
||||
private CheckSaveListener mCheckSaveListener;
|
||||
private OnSettingsClickListener mOnSettingsClickListener;
|
||||
@VisibleForTesting
|
||||
protected String mKeyToRemoveOnGutsClosed;
|
||||
@@ -131,7 +127,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
private final UserContextProvider mContextTracker;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final ShadeController mShadeController;
|
||||
private final AppWidgetManager mAppWidgetManager;
|
||||
private NotifGutsViewListener mGutsListener;
|
||||
|
||||
/**
|
||||
@@ -144,7 +139,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
AccessibilityManager accessibilityManager,
|
||||
HighPriorityProvider highPriorityProvider,
|
||||
INotificationManager notificationManager,
|
||||
NotificationEntryManager notificationEntryManager,
|
||||
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
|
||||
LauncherApps launcherApps,
|
||||
ShortcutManager shortcutManager,
|
||||
@@ -173,17 +167,15 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mOnUserInteractionCallback = onUserInteractionCallback;
|
||||
mShadeController = shadeController;
|
||||
mAppWidgetManager = AppWidgetManager.getInstance(context);
|
||||
|
||||
dumpManager.registerDumpable(this);
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter,
|
||||
NotificationListContainer listContainer,
|
||||
CheckSaveListener checkSave, OnSettingsClickListener onSettingsClick) {
|
||||
OnSettingsClickListener onSettingsClick) {
|
||||
mPresenter = presenter;
|
||||
mListContainer = listContainer;
|
||||
mCheckSaveListener = checkSave;
|
||||
mOnSettingsClickListener = onSettingsClick;
|
||||
}
|
||||
|
||||
@@ -218,14 +210,11 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
}
|
||||
|
||||
private void startAppDetailsSettingsActivity(String packageName, final int appUid,
|
||||
final NotificationChannel channel, ExpandableNotificationRow row) {
|
||||
ExpandableNotificationRow row) {
|
||||
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", packageName, null));
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
|
||||
intent.putExtra(Settings.EXTRA_APP_UID, appUid);
|
||||
if (channel != null) {
|
||||
intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
|
||||
}
|
||||
mNotificationActivityStarter.startNotificationGutsIntent(intent, appUid, row);
|
||||
}
|
||||
|
||||
@@ -233,7 +222,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
ExpandableNotificationRow row) {
|
||||
if (ops.contains(OP_SYSTEM_ALERT_WINDOW)) {
|
||||
if (ops.contains(OP_CAMERA) || ops.contains(OP_RECORD_AUDIO)) {
|
||||
startAppDetailsSettingsActivity(pkg, uid, null, row);
|
||||
startAppDetailsSettingsActivity(pkg, uid, row);
|
||||
} else {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_OVERLAY_PERMISSION);
|
||||
intent.setData(Uri.fromParts("package", pkg, null));
|
||||
|
||||
@@ -196,14 +196,12 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationShelfController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.PowerButtonReveal;
|
||||
import com.android.systemui.statusbar.PulseExpansionHandler;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.core.StatusBarInitializer;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
|
||||
@@ -515,7 +513,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
protected final NotificationEntryManager mEntryManager;
|
||||
private final NotificationGutsManager mGutsManager;
|
||||
private final NotificationLogger mNotificationLogger;
|
||||
private final NotificationViewHierarchyManager mViewHierarchyManager;
|
||||
private final PanelExpansionStateManager mPanelExpansionStateManager;
|
||||
private final KeyguardViewMediator mKeyguardViewMediator;
|
||||
protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
|
||||
@@ -651,7 +648,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
private final Optional<Bubbles> mBubblesOptional;
|
||||
private final Bubbles.BubbleExpandListener mBubbleExpandListener;
|
||||
private final Optional<StartingSurface> mStartingSurfaceOptional;
|
||||
private final NotifPipelineFlags mNotifPipelineFlags;
|
||||
|
||||
private final ActivityIntentHelper mActivityIntentHelper;
|
||||
private NotificationStackScrollLayoutController mStackScrollerController;
|
||||
@@ -693,7 +689,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
NotificationGutsManager notificationGutsManager,
|
||||
NotificationLogger notificationLogger,
|
||||
NotificationInterruptStateProvider notificationInterruptStateProvider,
|
||||
NotificationViewHierarchyManager notificationViewHierarchyManager,
|
||||
PanelExpansionStateManager panelExpansionStateManager,
|
||||
KeyguardViewMediator keyguardViewMediator,
|
||||
DisplayMetrics displayMetrics,
|
||||
@@ -756,7 +751,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
WallpaperManager wallpaperManager,
|
||||
Optional<StartingSurface> startingSurfaceOptional,
|
||||
ActivityLaunchAnimator activityLaunchAnimator,
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
InteractionJankMonitor jankMonitor,
|
||||
DeviceStateManager deviceStateManager,
|
||||
WiredChargingRippleController wiredChargingRippleController,
|
||||
@@ -783,7 +777,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
mGutsManager = notificationGutsManager;
|
||||
mNotificationLogger = notificationLogger;
|
||||
mNotificationInterruptStateProvider = notificationInterruptStateProvider;
|
||||
mViewHierarchyManager = notificationViewHierarchyManager;
|
||||
mPanelExpansionStateManager = panelExpansionStateManager;
|
||||
mKeyguardViewMediator = keyguardViewMediator;
|
||||
mDisplayMetrics = displayMetrics;
|
||||
@@ -844,7 +837,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
||||
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
mStartingSurfaceOptional = startingSurfaceOptional;
|
||||
mNotifPipelineFlags = notifPipelineFlags;
|
||||
mDreamManager = dreamManager;
|
||||
lockscreenShadeTransitionController.setCentralSurfaces(this);
|
||||
statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||
import com.android.systemui.shade.NotificationPanelViewController;
|
||||
import com.android.systemui.shade.NotificationShadeWindowView;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
@@ -50,7 +49,6 @@ import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.AboveShelfObserver;
|
||||
@@ -82,7 +80,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final NotificationViewHierarchyManager mViewHierarchyManager;
|
||||
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||
private final NotifShadeEventSource mNotifShadeEventSource;
|
||||
@@ -94,10 +91,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
private final HeadsUpManagerPhone mHeadsUpManager;
|
||||
private final AboveShelfObserver mAboveShelfObserver;
|
||||
private final DozeScrimController mDozeScrimController;
|
||||
private final ScrimController mScrimController;
|
||||
private final KeyguardIndicationController mKeyguardIndicationController;
|
||||
private final CentralSurfaces mCentralSurfaces;
|
||||
private final com.android.systemui.shade.ShadeController mShadeController;
|
||||
private final LockscreenShadeTransitionController mShadeTransitionController;
|
||||
private final CommandQueue mCommandQueue;
|
||||
|
||||
@@ -112,23 +107,21 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
protected boolean mVrMode;
|
||||
|
||||
@Inject
|
||||
StatusBarNotificationPresenter(Context context,
|
||||
StatusBarNotificationPresenter(
|
||||
Context context,
|
||||
NotificationPanelViewController panel,
|
||||
HeadsUpManagerPhone headsUp,
|
||||
NotificationShadeWindowView statusBarWindow,
|
||||
ActivityStarter activityStarter,
|
||||
NotificationStackScrollLayoutController stackScrollerController,
|
||||
DozeScrimController dozeScrimController,
|
||||
ScrimController scrimController,
|
||||
NotificationShadeWindowController notificationShadeWindowController,
|
||||
DynamicPrivacyController dynamicPrivacyController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
KeyguardIndicationController keyguardIndicationController,
|
||||
CentralSurfaces centralSurfaces,
|
||||
ShadeController shadeController,
|
||||
LockscreenShadeTransitionController shadeTransitionController,
|
||||
CommandQueue commandQueue,
|
||||
NotificationViewHierarchyManager notificationViewHierarchyManager,
|
||||
NotificationLockscreenUserManager lockscreenUserManager,
|
||||
SysuiStatusBarStateController sysuiStatusBarStateController,
|
||||
NotifShadeEventSource notifShadeEventSource,
|
||||
@@ -149,10 +142,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
mKeyguardIndicationController = keyguardIndicationController;
|
||||
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
||||
mCentralSurfaces = centralSurfaces;
|
||||
mShadeController = shadeController;
|
||||
mShadeTransitionController = shadeTransitionController;
|
||||
mCommandQueue = commandQueue;
|
||||
mViewHierarchyManager = notificationViewHierarchyManager;
|
||||
mLockscreenUserManager = lockscreenUserManager;
|
||||
mStatusBarStateController = sysuiStatusBarStateController;
|
||||
mNotifShadeEventSource = notifShadeEventSource;
|
||||
@@ -166,7 +157,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
R.id.notification_container_parent));
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
mDozeScrimController = dozeScrimController;
|
||||
mScrimController = scrimController;
|
||||
mKeyguardManager = context.getSystemService(KeyguardManager.class);
|
||||
mBarService = IStatusBarService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
|
||||
@@ -187,16 +177,13 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
|
||||
initController.addPostInitTask(() -> {
|
||||
mKeyguardIndicationController.init();
|
||||
mViewHierarchyManager.setUpWithPresenter(this,
|
||||
stackScrollerController.getNotifStackController(),
|
||||
mNotifListContainer);
|
||||
mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
|
||||
mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
|
||||
notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
|
||||
mLockscreenUserManager.setUpWithPresenter(this);
|
||||
mMediaManager.setUpWithPresenter(this);
|
||||
mGutsManager.setUpWithPresenter(
|
||||
this, mNotifListContainer, mCheckSaveListener, mOnSettingsClickListener);
|
||||
this, mNotifListContainer, mOnSettingsClickListener);
|
||||
// ForegroundServiceNotificationListener adds its listener in its constructor
|
||||
// but we need to request it here in order for it to be instantiated.
|
||||
// TODO: figure out how to do this correctly once Dependency.get() is gone.
|
||||
@@ -232,24 +219,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNotificationViews(final String reason) {
|
||||
if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
|
||||
return;
|
||||
}
|
||||
// The function updateRowStates depends on both of these being non-null, so check them here.
|
||||
// We may be called before they are set from DeviceProvisionedController's callback.
|
||||
if (mScrimController == null) return;
|
||||
|
||||
// Do not modify the notifications during collapse.
|
||||
if (isCollapsing()) {
|
||||
mShadeController.addPostCollapseAction(() -> updateNotificationViews(reason));
|
||||
return;
|
||||
}
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
mNotificationPanel.updateNotificationViews(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserSwitched(int newUserId) {
|
||||
// Begin old BaseStatusBar.userSwitched
|
||||
@@ -303,11 +272,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
mMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateRowStates() {
|
||||
mNotificationPanel.onUpdateRowStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpandClicked(NotificationEntry clickedEntry, View clickedView,
|
||||
boolean nowExpanded) {
|
||||
|
||||
@@ -30,13 +30,11 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
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.HeadsUpManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
@@ -55,11 +53,8 @@ import org.mockito.MockitoAnnotations;
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
public class NonPhoneDependencyTest extends SysuiTestCase {
|
||||
@Mock private NotificationPresenter mPresenter;
|
||||
@Mock private NotifStackController mStackController;
|
||||
@Mock private NotificationListContainer mListContainer;
|
||||
@Mock
|
||||
private NotificationEntryListener mEntryListener;
|
||||
@Mock private HeadsUpManager mHeadsUpManager;
|
||||
@Mock private NotificationEntryListener mEntryListener;
|
||||
@Mock private RemoteInputController.Delegate mDelegate;
|
||||
@Mock private NotificationRemoteInputManager.Callback mRemoteInputManagerCallback;
|
||||
@Mock private CheckSaveListener mCheckSaveListener;
|
||||
@@ -79,25 +74,20 @@ public class NonPhoneDependencyTest extends SysuiTestCase {
|
||||
mDependency.injectMockDependency(ShadeController.class);
|
||||
NotificationEntryManager entryManager = Dependency.get(NotificationEntryManager.class);
|
||||
NotificationGutsManager gutsManager = Dependency.get(NotificationGutsManager.class);
|
||||
NotificationListener notificationListener = Dependency.get(NotificationListener.class);
|
||||
NotificationLogger notificationLogger = Dependency.get(NotificationLogger.class);
|
||||
NotificationMediaManager mediaManager = Dependency.get(NotificationMediaManager.class);
|
||||
NotificationRemoteInputManager remoteInputManager =
|
||||
Dependency.get(NotificationRemoteInputManager.class);
|
||||
NotificationLockscreenUserManager lockscreenUserManager =
|
||||
Dependency.get(NotificationLockscreenUserManager.class);
|
||||
NotificationViewHierarchyManager viewHierarchyManager =
|
||||
Dependency.get(NotificationViewHierarchyManager.class);
|
||||
entryManager.setUpWithPresenter(mPresenter);
|
||||
entryManager.addNotificationEntryListener(mEntryListener);
|
||||
gutsManager.setUpWithPresenter(mPresenter, mListContainer,
|
||||
mCheckSaveListener, mOnSettingsClickListener);
|
||||
mOnSettingsClickListener);
|
||||
notificationLogger.setUpWithContainer(mListContainer);
|
||||
mediaManager.setUpWithPresenter(mPresenter);
|
||||
remoteInputManager.setUpWithCallback(mRemoteInputManagerCallback,
|
||||
mDelegate);
|
||||
lockscreenUserManager.setUpWithPresenter(mPresenter);
|
||||
viewHierarchyManager.setUpWithPresenter(mPresenter, mStackController, mListContainer);
|
||||
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
assertFalse(mDependency.hasInstantiatedDependency(NotificationShadeWindowController.class));
|
||||
|
||||
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
|
||||
import com.android.systemui.statusbar.notification.DynamicChildBindController;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
|
||||
@Mock private NotificationPresenter mPresenter;
|
||||
@Mock private NotifStackController mStackController;
|
||||
@Spy private FakeListContainer mListContainer = new FakeListContainer();
|
||||
|
||||
// Dependency mocks:
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private NotifPipelineFlags mNotifPipelineFlags;
|
||||
@Mock private NotificationEntryManager mEntryManager;
|
||||
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
@Mock private NotificationGroupManagerLegacy mGroupManager;
|
||||
@Mock private VisualStabilityManager mVisualStabilityManager;
|
||||
|
||||
private TestableLooper mTestableLooper;
|
||||
private Handler mHandler;
|
||||
private NotificationViewHierarchyManager mViewHierarchyManager;
|
||||
private NotificationTestHelper mHelper;
|
||||
private boolean mMadeReentrantCall = false;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
allowTestableLooperAsMainThread();
|
||||
mHandler = Handler.createAsync(mTestableLooper.getLooper());
|
||||
|
||||
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
|
||||
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
|
||||
mLockscreenUserManager);
|
||||
mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
|
||||
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
|
||||
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
|
||||
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
|
||||
|
||||
when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
|
||||
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
|
||||
|
||||
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
|
||||
|
||||
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
|
||||
mHandler, mFeatureFlags, mLockscreenUserManager, mGroupManager,
|
||||
mVisualStabilityManager,
|
||||
mock(StatusBarStateControllerImpl.class), mEntryManager,
|
||||
mock(KeyguardBypassController.class),
|
||||
Optional.of(mock(Bubbles.class)),
|
||||
mock(DynamicPrivacyController.class),
|
||||
mock(DynamicChildBindController.class),
|
||||
mock(LowPriorityInflationHelper.class),
|
||||
mock(AssistantFeedbackController.class),
|
||||
mNotifPipelineFlags,
|
||||
mock(KeyguardUpdateMonitor.class),
|
||||
mock(KeyguardStateController.class));
|
||||
mViewHierarchyManager.setUpWithPresenter(mPresenter, mStackController, mListContainer);
|
||||
}
|
||||
|
||||
private NotificationEntry createEntry() throws Exception {
|
||||
ExpandableNotificationRow row = mHelper.createRow();
|
||||
return row.getEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationsBecomingBundled() throws Exception {
|
||||
// Tests 3 top level notifications becoming a single bundled notification with |entry0| as
|
||||
// the summary.
|
||||
NotificationEntry entry0 = createEntry();
|
||||
NotificationEntry entry1 = createEntry();
|
||||
NotificationEntry entry2 = createEntry();
|
||||
|
||||
// Set up the prior state to look like three top level notifications.
|
||||
mListContainer.addContainerView(entry0.getRow());
|
||||
mListContainer.addContainerView(entry1.getRow());
|
||||
mListContainer.addContainerView(entry2.getRow());
|
||||
when(mEntryManager.getVisibleNotifications()).thenReturn(
|
||||
Lists.newArrayList(entry0, entry1, entry2));
|
||||
|
||||
// Set up group manager to report that they should be bundled now.
|
||||
when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
|
||||
when(mGroupManager.isChildInGroup(entry1)).thenReturn(true);
|
||||
when(mGroupManager.isChildInGroup(entry2)).thenReturn(true);
|
||||
when(mGroupManager.getGroupSummary(entry1)).thenReturn(entry0);
|
||||
when(mGroupManager.getGroupSummary(entry2)).thenReturn(entry0);
|
||||
|
||||
// Run updateNotifications - the view hierarchy should be reorganized.
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
|
||||
verify(mListContainer).notifyGroupChildAdded(entry1.getRow());
|
||||
verify(mListContainer).notifyGroupChildAdded(entry2.getRow());
|
||||
assertTrue(Lists.newArrayList(entry0.getRow()).equals(mListContainer.mRows));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationsBecomingUnbundled() throws Exception {
|
||||
// Tests a bundled notification becoming three top level notifications.
|
||||
NotificationEntry entry0 = createEntry();
|
||||
NotificationEntry entry1 = createEntry();
|
||||
NotificationEntry entry2 = createEntry();
|
||||
entry0.getRow().addChildNotification(entry1.getRow());
|
||||
entry0.getRow().addChildNotification(entry2.getRow());
|
||||
|
||||
// Set up the prior state to look like one top level notification.
|
||||
mListContainer.addContainerView(entry0.getRow());
|
||||
when(mEntryManager.getVisibleNotifications()).thenReturn(
|
||||
Lists.newArrayList(entry0, entry1, entry2));
|
||||
|
||||
// Set up group manager to report that they should not be bundled now.
|
||||
when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
|
||||
when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
|
||||
when(mGroupManager.isChildInGroup(entry2)).thenReturn(false);
|
||||
|
||||
// Run updateNotifications - the view hierarchy should be reorganized.
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
|
||||
verify(mListContainer).notifyGroupChildRemoved(
|
||||
entry1.getRow(), entry0.getRow().getChildrenContainer());
|
||||
verify(mListContainer).notifyGroupChildRemoved(
|
||||
entry2.getRow(), entry0.getRow().getChildrenContainer());
|
||||
assertTrue(
|
||||
Lists.newArrayList(entry0.getRow(), entry1.getRow(), entry2.getRow())
|
||||
.equals(mListContainer.mRows));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationsBecomingSuppressed() throws Exception {
|
||||
// Tests two top level notifications becoming a suppressed summary and a child.
|
||||
NotificationEntry entry0 = createEntry();
|
||||
NotificationEntry entry1 = createEntry();
|
||||
entry0.getRow().addChildNotification(entry1.getRow());
|
||||
|
||||
// Set up the prior state to look like a top level notification.
|
||||
mListContainer.addContainerView(entry0.getRow());
|
||||
when(mEntryManager.getVisibleNotifications()).thenReturn(
|
||||
Lists.newArrayList(entry0, entry1));
|
||||
|
||||
// Set up group manager to report a suppressed summary now.
|
||||
when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
|
||||
when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
|
||||
when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true);
|
||||
|
||||
// Run updateNotifications - the view hierarchy should be reorganized.
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
|
||||
verify(mListContainer).notifyGroupChildRemoved(
|
||||
entry1.getRow(), entry0.getRow().getChildrenContainer());
|
||||
assertTrue(Lists.newArrayList(entry0.getRow(), entry1.getRow()).equals(mListContainer.mRows));
|
||||
assertEquals(View.GONE, entry0.getRow().getVisibility());
|
||||
assertEquals(View.VISIBLE, entry1.getRow().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() {
|
||||
// GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews()
|
||||
mMadeReentrantCall = false;
|
||||
doAnswer((invocation) -> {
|
||||
if (!mMadeReentrantCall) {
|
||||
mMadeReentrantCall = true;
|
||||
mViewHierarchyManager.onDynamicPrivacyChanged();
|
||||
}
|
||||
return null;
|
||||
}).when(mListContainer).onNotificationViewUpdateFinished();
|
||||
|
||||
// WHEN we call updateNotificationViews()
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
|
||||
// THEN onNotificationViewUpdateFinished() is only called once
|
||||
verify(mListContainer).onNotificationViewUpdateFinished();
|
||||
|
||||
// WHEN we drain the looper
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// THEN updateNotificationViews() is called a second time (for the reentrant call)
|
||||
verify(mListContainer, times(2)).onNotificationViewUpdateFinished();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleReentrantCallsToOnDynamicPrivacyChangedOnlyPostOnce() {
|
||||
// GIVEN a ListContainer that will make many re-entrant calls to updateNotificationViews()
|
||||
mMadeReentrantCall = false;
|
||||
doAnswer((invocation) -> {
|
||||
if (!mMadeReentrantCall) {
|
||||
mMadeReentrantCall = true;
|
||||
mViewHierarchyManager.onDynamicPrivacyChanged();
|
||||
mViewHierarchyManager.onDynamicPrivacyChanged();
|
||||
mViewHierarchyManager.onDynamicPrivacyChanged();
|
||||
mViewHierarchyManager.onDynamicPrivacyChanged();
|
||||
}
|
||||
return null;
|
||||
}).when(mListContainer).onNotificationViewUpdateFinished();
|
||||
|
||||
// WHEN we call updateNotificationViews() and drain the looper
|
||||
mViewHierarchyManager.updateNotificationViews();
|
||||
verify(mListContainer).onNotificationViewUpdateFinished();
|
||||
clearInvocations(mListContainer);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
// THEN updateNotificationViews() is called only one more time
|
||||
verify(mListContainer).onNotificationViewUpdateFinished();
|
||||
}
|
||||
|
||||
private class FakeListContainer implements NotificationListContainer {
|
||||
final LinearLayout mLayout = new LinearLayout(mContext);
|
||||
final List<View> mRows = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
public void setChildTransferInProgress(boolean childTransferInProgress) {}
|
||||
|
||||
@Override
|
||||
public void changeViewPosition(ExpandableView child, int newIndex) {
|
||||
mRows.remove(child);
|
||||
mRows.add(newIndex, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyGroupChildAdded(ExpandableView row) {}
|
||||
|
||||
@Override
|
||||
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}
|
||||
|
||||
@Override
|
||||
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}
|
||||
|
||||
@Override
|
||||
public void generateChildOrderChangedEvent() {}
|
||||
|
||||
@Override
|
||||
public void onReset(ExpandableView view) {}
|
||||
|
||||
@Override
|
||||
public int getContainerChildCount() {
|
||||
return mRows.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getContainerChildAt(int i) {
|
||||
return mRows.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeContainerView(View v) {
|
||||
mLayout.removeView(v);
|
||||
mRows.remove(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotificationActivityStarter(
|
||||
NotificationActivityStarter notificationActivityStarter) {}
|
||||
|
||||
@Override
|
||||
public void addContainerView(View v) {
|
||||
mLayout.addView(v);
|
||||
mRows.add(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContainerViewAt(View v, int index) {
|
||||
mLayout.addView(v, index);
|
||||
mRows.add(index, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxDisplayedNotifications(int maxNotifications) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup getViewParentForNotification(NotificationEntry entry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeightChanged(ExpandableView view, boolean animate) {}
|
||||
|
||||
@Override
|
||||
public void resetExposedMenuView(boolean animate, boolean force) {}
|
||||
|
||||
@Override
|
||||
public NotificationSwipeActionHelper getSwipeActionHelper() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUpViewStateForEntry(NotificationEntry entry) { }
|
||||
|
||||
@Override
|
||||
public boolean isInVisibleLocation(NotificationEntry entry) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChildLocationsChangedListener(
|
||||
NotificationLogger.OnChildLocationsChangedListener listener) {}
|
||||
|
||||
@Override
|
||||
public boolean hasPulsingNotifications() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationViewUpdateFinished() { }
|
||||
}
|
||||
}
|
||||
@@ -77,10 +77,8 @@ import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
|
||||
import com.android.systemui.statusbar.RankingBuilder;
|
||||
import com.android.systemui.statusbar.SmartReplyController;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreMocksKt;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
@@ -91,7 +89,6 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest;
|
||||
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
@@ -115,9 +112,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link NotificationEntryManager}. This test will not test any interactions with
|
||||
* inflation. Instead, for functional inflation tests, see
|
||||
* {@link NotificationEntryManagerInflationTest}.
|
||||
* Unit tests for {@link NotificationEntryManager}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@@ -205,7 +200,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
mStats = defaultStats(mEntry);
|
||||
mSbn = mEntry.getSbn();
|
||||
|
||||
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
|
||||
mEntryManager = new NotificationEntryManager(
|
||||
mLogger,
|
||||
mGroupManager,
|
||||
@@ -214,7 +208,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
() -> mRemoteInputManager,
|
||||
mLeakDetector,
|
||||
mStatusBarService,
|
||||
NotifLiveDataStoreMocksKt.createNotifLiveDataStoreImplMock(),
|
||||
mock(DumpManager.class),
|
||||
mBgExecutor
|
||||
);
|
||||
@@ -230,7 +223,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class),
|
||||
mEnvironment));
|
||||
mEntryManager.setUpWithPresenter(mPresenter);
|
||||
mEntryManager.addNotificationEntryListener(mEntryListener);
|
||||
mEntryManager.addCollectionListener(mNotifCollectionListener);
|
||||
mEntryManager.addNotificationRemoveInterceptor(mRemoveInterceptor);
|
||||
@@ -272,17 +264,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
assertEquals(entry.getUserSentiment(), Ranking.USER_SENTIMENT_NEUTRAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotification_updatesUserSentiment() {
|
||||
mEntryManager.addActiveNotificationForTest(mEntry);
|
||||
setUserSentiment(
|
||||
mEntry.getKey(), Ranking.USER_SENTIMENT_NEGATIVE);
|
||||
|
||||
mEntryManager.updateNotification(mSbn, mRankingMap);
|
||||
|
||||
assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, mEntry.getUserSentiment());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotification_prePostEntryOrder() throws Exception {
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
@@ -294,7 +275,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
// Ensure that update callbacks happen in correct order
|
||||
InOrder order = inOrder(mEntryListener, mPresenter, mEntryListener);
|
||||
order.verify(mEntryListener).onPreEntryUpdated(mEntry);
|
||||
order.verify(mPresenter).updateNotificationViews(any());
|
||||
order.verify(mEntryListener).onPostEntryUpdated(mEntry);
|
||||
}
|
||||
|
||||
@@ -305,7 +285,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
|
||||
mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
|
||||
|
||||
verify(mPresenter).updateNotificationViews(any());
|
||||
verify(mEntryListener).onEntryRemoved(
|
||||
argThat(matchEntryOnKey()), any(),
|
||||
eq(false) /* removedByUser */, eq(UNDEFINED_DISMISS_REASON));
|
||||
@@ -378,23 +357,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
argThat(matchEntryOnKey()), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationRanking() {
|
||||
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
||||
when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
|
||||
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
|
||||
|
||||
mEntry.setRow(mRow);
|
||||
mEntry.setInflationTask(mAsyncInflationTask);
|
||||
mEntryManager.addActiveNotificationForTest(mEntry);
|
||||
setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
|
||||
|
||||
mEntryManager.updateNotificationRanking(mRankingMap);
|
||||
assertEquals(1, mEntry.getSmartActions().size());
|
||||
assertEquals("action", mEntry.getSmartActions().get(0).title);
|
||||
verify(mEntryListener).onNotificationRankingUpdated(mRankingMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationRanking_noChange() {
|
||||
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
||||
@@ -408,20 +370,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
assertThat(mEntry.getSmartActions()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationRanking_rowNotInflatedYet() {
|
||||
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
||||
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
|
||||
|
||||
mEntry.setRow(null);
|
||||
mEntryManager.addActiveNotificationForTest(mEntry);
|
||||
setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
|
||||
|
||||
mEntryManager.updateNotificationRanking(mRankingMap);
|
||||
assertEquals(1, mEntry.getSmartActions().size());
|
||||
assertEquals("action", mEntry.getSmartActions().get(0).title);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotificationRanking_pendingNotification() {
|
||||
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
||||
@@ -613,31 +561,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
|
||||
/* Tests annexed from NotificationDataTest go here */
|
||||
|
||||
@Test
|
||||
public void testChannelIsSetWhenAdded() {
|
||||
NotificationChannel nc = new NotificationChannel(
|
||||
"testId",
|
||||
"testName",
|
||||
IMPORTANCE_DEFAULT);
|
||||
|
||||
Ranking r = new RankingBuilder()
|
||||
.setKey(mEntry.getKey())
|
||||
.setChannel(nc)
|
||||
.build();
|
||||
|
||||
RankingMap rm = new RankingMap(new Ranking[] { r });
|
||||
|
||||
// GIVEN: a notification is added, and the ranking updated
|
||||
mEntryManager.addActiveNotificationForTest(mEntry);
|
||||
mEntryManager.updateRanking(rm, "testReason");
|
||||
|
||||
// THEN the notification entry better have a channel on it
|
||||
assertEquals(
|
||||
"Channel must be set when adding a notification",
|
||||
nc.getName(),
|
||||
mEntry.getChannel().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications() {
|
||||
Notification.Builder n = new Notification.Builder(mContext, "di")
|
||||
|
||||
@@ -118,7 +118,6 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
|
||||
mPowerManager,
|
||||
mDreamManager,
|
||||
mAmbientDisplayConfiguration,
|
||||
mNotificationFilter,
|
||||
mBatteryController,
|
||||
mStatusBarStateController,
|
||||
mKeyguardStateController,
|
||||
|
||||
@@ -1,467 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.row;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.os.Handler;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.NotificationListenerService.Ranking;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.util.NotificationMessagingUtil;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||
import com.android.systemui.classifier.FalsingManagerFake;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.media.MediaFeatureFlag;
|
||||
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.NotificationListener;
|
||||
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.SbnBuilder;
|
||||
import com.android.systemui.statusbar.SmartReplyController;
|
||||
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationClicker;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreMocksKt;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.icon.IconBuilder;
|
||||
import com.android.systemui.statusbar.notification.icon.IconManager;
|
||||
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
|
||||
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
|
||||
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
|
||||
import com.android.systemui.statusbar.policy.SmartReplyConstants;
|
||||
import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
|
||||
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.leak.LeakDetector;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
import com.android.systemui.wmshell.BubblesManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* Functional tests for notification inflation from {@link NotificationEntryManager}.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
public class NotificationEntryManagerInflationTest extends SysuiTestCase {
|
||||
|
||||
private static final String TEST_TITLE = "Title";
|
||||
private static final String TEST_TEXT = "Text";
|
||||
private static final long TIMEOUT_TIME = 10000;
|
||||
private static final Runnable TIMEOUT_RUNNABLE = () -> {
|
||||
throw new RuntimeException("Timed out waiting to inflate");
|
||||
};
|
||||
|
||||
@Mock private NotificationListener mNotificationListener;
|
||||
@Mock private NotificationPresenter mPresenter;
|
||||
@Mock private NotificationEntryManager.KeyguardEnvironment mEnvironment;
|
||||
@Mock private NotificationListContainer mListContainer;
|
||||
@Mock private NotificationEntryListener mEntryListener;
|
||||
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
|
||||
@Mock private HeadsUpManager mHeadsUpManager;
|
||||
@Mock private NotificationInterruptStateProvider mNotificationInterruptionStateProvider;
|
||||
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
@Mock private NotificationGutsManager mGutsManager;
|
||||
@Mock private NotificationRemoteInputManager mRemoteInputManager;
|
||||
@Mock private NotificationMediaManager mNotificationMediaManager;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private ExpandableNotificationRowComponent.Builder mExpandableNotificationRowComponentBuilder;
|
||||
@Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
|
||||
@Mock private KeyguardBypassController mKeyguardBypassController;
|
||||
@Mock private StatusBarStateController mStatusBarStateController;
|
||||
|
||||
@Mock private NotificationGroupManagerLegacy mGroupMembershipManager;
|
||||
@Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
|
||||
@Mock private NotifPipelineFlags mNotifPipelineFlags;
|
||||
@Mock private LeakDetector mLeakDetector;
|
||||
|
||||
@Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
|
||||
@Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
|
||||
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
@Mock private InflatedSmartReplyState mInflatedSmartReplyState;
|
||||
@Mock private InflatedSmartReplyViewHolder mInflatedSmartReplies;
|
||||
|
||||
private StatusBarNotification mSbn;
|
||||
private NotificationListenerService.RankingMap mRankingMap;
|
||||
private NotificationEntryManager mEntryManager;
|
||||
private NotificationRowBinderImpl mRowBinder;
|
||||
private Handler mHandler;
|
||||
private FakeExecutor mBgExecutor;
|
||||
private RowContentBindStage mRowContentBindStage;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mDependency.injectMockDependency(SmartReplyController.class);
|
||||
mDependency.injectMockDependency(MediaOutputDialogFactory.class);
|
||||
|
||||
mHandler = Handler.createAsync(TestableLooper.get(this).getLooper());
|
||||
|
||||
// Add an action so heads up content views are made
|
||||
Notification.Action action = new Notification.Action.Builder(null, null, null).build();
|
||||
Notification notification = new Notification.Builder(mContext)
|
||||
.setSmallIcon(R.drawable.ic_person)
|
||||
.setContentTitle(TEST_TITLE)
|
||||
.setContentText(TEST_TEXT)
|
||||
.setActions(action)
|
||||
.build();
|
||||
mSbn = new SbnBuilder()
|
||||
.setNotification(notification)
|
||||
.build();
|
||||
|
||||
when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
|
||||
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
|
||||
|
||||
mEntryManager = new NotificationEntryManager(
|
||||
mock(NotificationEntryManagerLogger.class),
|
||||
mGroupMembershipManager,
|
||||
mNotifPipelineFlags,
|
||||
() -> mRowBinder,
|
||||
() -> mRemoteInputManager,
|
||||
mLeakDetector,
|
||||
mock(IStatusBarService.class),
|
||||
NotifLiveDataStoreMocksKt.createNotifLiveDataStoreImplMock(),
|
||||
mock(DumpManager.class),
|
||||
mBgExecutor
|
||||
);
|
||||
mEntryManager.initialize(
|
||||
mNotificationListener,
|
||||
new NotificationRankingManager(
|
||||
() -> mock(NotificationMediaManager.class),
|
||||
mGroupMembershipManager,
|
||||
mHeadsUpManager,
|
||||
mock(NotificationFilter.class),
|
||||
mock(NotificationEntryManagerLogger.class),
|
||||
mock(NotificationSectionsFeatureManager.class),
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class),
|
||||
mEnvironment));
|
||||
|
||||
NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
|
||||
NotifBindPipeline pipeline = new NotifBindPipeline(
|
||||
mEntryManager,
|
||||
mock(NotifBindPipelineLogger.class),
|
||||
TestableLooper.get(this).getLooper());
|
||||
mBgExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
NotificationContentInflater binder = new NotificationContentInflater(
|
||||
cache,
|
||||
mRemoteInputManager,
|
||||
mock(ConversationNotificationProcessor.class),
|
||||
mock(MediaFeatureFlag.class),
|
||||
mBgExecutor,
|
||||
new SmartReplyStateInflater() {
|
||||
@Override
|
||||
public InflatedSmartReplyState inflateSmartReplyState(NotificationEntry entry) {
|
||||
return mInflatedSmartReplyState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InflatedSmartReplyViewHolder inflateSmartReplyViewHolder(
|
||||
Context sysuiContext, Context notifPackageContext,
|
||||
NotificationEntry entry,
|
||||
InflatedSmartReplyState existingSmartReplyState,
|
||||
InflatedSmartReplyState newSmartReplyState) {
|
||||
return mInflatedSmartReplies;
|
||||
}
|
||||
});
|
||||
mRowContentBindStage = new RowContentBindStage(
|
||||
binder,
|
||||
mock(NotifInflationErrorManager.class),
|
||||
mock(RowContentBindStageLogger.class));
|
||||
pipeline.setStage(mRowContentBindStage);
|
||||
|
||||
ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
|
||||
ArgumentCaptor.forClass(ExpandableNotificationRow.class);
|
||||
when(mExpandableNotificationRowComponentBuilder
|
||||
.expandableNotificationRow(viewCaptor.capture()))
|
||||
.thenReturn(mExpandableNotificationRowComponentBuilder);
|
||||
when(mExpandableNotificationRowComponentBuilder.build())
|
||||
.thenReturn(mExpandableNotificationRowComponent);
|
||||
|
||||
when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
|
||||
.thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
|
||||
new ExpandableNotificationRowController(
|
||||
viewCaptor.getValue(),
|
||||
mock(ActivatableNotificationViewController.class),
|
||||
mock(RemoteInputViewSubcomponent.Factory.class),
|
||||
mock(MetricsLogger.class),
|
||||
mListContainer,
|
||||
mNotificationMediaManager,
|
||||
mock(SmartReplyConstants.class),
|
||||
mock(SmartReplyController.class),
|
||||
mock(PluginManager.class),
|
||||
new FakeSystemClock(),
|
||||
"FOOBAR",
|
||||
"FOOBAR",
|
||||
mKeyguardBypassController,
|
||||
mGroupMembershipManager,
|
||||
mGroupExpansionManager,
|
||||
mRowContentBindStage,
|
||||
mock(NotificationLogger.class),
|
||||
mHeadsUpManager,
|
||||
mPresenter,
|
||||
mStatusBarStateController,
|
||||
mGutsManager,
|
||||
true,
|
||||
null,
|
||||
new FalsingManagerFake(),
|
||||
new FalsingCollectorFake(),
|
||||
mock(FeatureFlags.class),
|
||||
mPeopleNotificationIdentifier,
|
||||
Optional.of(mock(BubblesManager.class)),
|
||||
mock(ExpandableNotificationRowDragController.class)));
|
||||
|
||||
when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
|
||||
.thenReturn(mNotificationRowComponentBuilder);
|
||||
when(mNotificationRowComponentBuilder.build()).thenReturn(
|
||||
() -> mActivatableNotificationViewController);
|
||||
|
||||
mRowBinder = new NotificationRowBinderImpl(
|
||||
mContext,
|
||||
new NotificationMessagingUtil(mContext),
|
||||
mRemoteInputManager,
|
||||
mLockscreenUserManager,
|
||||
pipeline,
|
||||
mRowContentBindStage,
|
||||
RowInflaterTask::new,
|
||||
mExpandableNotificationRowComponentBuilder,
|
||||
new IconManager(
|
||||
mEntryManager,
|
||||
mock(LauncherApps.class),
|
||||
new IconBuilder(mContext)),
|
||||
mock(LowPriorityInflationHelper.class),
|
||||
mNotifPipelineFlags);
|
||||
|
||||
mEntryManager.setUpWithPresenter(mPresenter);
|
||||
mEntryManager.addNotificationEntryListener(mEntryListener);
|
||||
|
||||
mRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
|
||||
mRowBinder.setNotificationClicker(mock(NotificationClicker.class));
|
||||
|
||||
Ranking ranking = new Ranking();
|
||||
ranking.populate(
|
||||
mSbn.getKey(),
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
IMPORTANCE_DEFAULT,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
Ranking.USER_SENTIMENT_NEUTRAL,
|
||||
false,
|
||||
-1,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
0,
|
||||
false
|
||||
);
|
||||
mRankingMap = new NotificationListenerService.RankingMap(new Ranking[] {ranking});
|
||||
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
// Don't leave anything on main thread
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNotification() {
|
||||
// WHEN a notification is added
|
||||
mEntryManager.addNotification(mSbn, mRankingMap);
|
||||
ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
|
||||
NotificationEntry.class);
|
||||
verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
|
||||
NotificationEntry entry = entryCaptor.getValue();
|
||||
|
||||
waitForInflation();
|
||||
|
||||
// THEN the notification has its row inflated
|
||||
assertNotNull(entry.getRow());
|
||||
assertNotNull(entry.getRow().getPrivateLayout().getContractedChild());
|
||||
|
||||
// THEN inflation callbacks are called
|
||||
verify(mBindCallback).onBindRow(entry.getRow());
|
||||
verify(mEntryListener, never()).onInflationError(any(), any());
|
||||
verify(mEntryListener).onEntryInflated(entry);
|
||||
verify(mEntryListener).onNotificationAdded(entry);
|
||||
|
||||
// THEN the notification is active
|
||||
assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
|
||||
|
||||
// THEN we update the presenter
|
||||
verify(mPresenter).updateNotificationViews(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateNotification() {
|
||||
// GIVEN a notification already added
|
||||
mEntryManager.addNotification(mSbn, mRankingMap);
|
||||
ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
|
||||
NotificationEntry.class);
|
||||
verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
|
||||
NotificationEntry entry = entryCaptor.getValue();
|
||||
waitForInflation();
|
||||
|
||||
Mockito.reset(mEntryListener);
|
||||
Mockito.reset(mPresenter);
|
||||
|
||||
// WHEN the notification is updated
|
||||
mEntryManager.updateNotification(mSbn, mRankingMap);
|
||||
|
||||
waitForInflation();
|
||||
|
||||
// THEN the notification has its row and inflated
|
||||
assertNotNull(entry.getRow());
|
||||
|
||||
// THEN inflation callbacks are called
|
||||
verify(mEntryListener, never()).onInflationError(any(), any());
|
||||
verify(mEntryListener).onEntryReinflated(entry);
|
||||
|
||||
// THEN we update the presenter
|
||||
verify(mPresenter).updateNotificationViews(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContentViewInflationDuringRowInflationInflatesCorrectViews() {
|
||||
// GIVEN a notification is added and the row is inflating
|
||||
mEntryManager.addNotification(mSbn, mRankingMap);
|
||||
ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
|
||||
NotificationEntry.class);
|
||||
verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
|
||||
NotificationEntry entry = entryCaptor.getValue();
|
||||
|
||||
// WHEN we try to bind a content view
|
||||
mRowContentBindStage.getStageParams(entry).requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
|
||||
mRowContentBindStage.requestRebind(entry, null);
|
||||
|
||||
waitForInflation();
|
||||
|
||||
// THEN the notification has its row and all relevant content views inflated
|
||||
assertNotNull(entry.getRow());
|
||||
assertNotNull(entry.getRow().getPrivateLayout().getContractedChild());
|
||||
assertNotNull(entry.getRow().getPrivateLayout().getHeadsUpChild());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for inflation to finish.
|
||||
*
|
||||
* A few things to note
|
||||
* 1) Row inflation is done via {@link AsyncLayoutInflater} on its own background thread that
|
||||
* calls back to main thread which is why we wait on main thread.
|
||||
* 2) Row *content* inflation is done on the {@link FakeExecutor} we pass in in this test class
|
||||
* so we control when that work is done. The callback is still always on the main thread.
|
||||
*/
|
||||
private void waitForInflation() {
|
||||
mHandler.postDelayed(TIMEOUT_RUNNABLE, TIMEOUT_TIME);
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
NotificationEntryListener inflationListener = new NotificationEntryListener() {
|
||||
@Override
|
||||
public void onEntryInflated(NotificationEntry entry) {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntryReinflated(NotificationEntry entry) {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInflationError(StatusBarNotification notification, Exception exception) {
|
||||
latch.countDown();
|
||||
}
|
||||
};
|
||||
mEntryManager.addNotificationEntryListener(inflationListener);
|
||||
while (latch.getCount() != 0) {
|
||||
mBgExecutor.runAllReady();
|
||||
TestableLooper.get(this).processMessages(1);
|
||||
}
|
||||
mHandler.removeCallbacks(TIMEOUT_RUNNABLE);
|
||||
mEntryManager.removeNotificationEntryListener(inflationListener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,13 +156,13 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
|
||||
mGutsManager = new NotificationGutsManager(mContext,
|
||||
() -> Optional.of(mCentralSurfaces), mHandler, mHandler, mAccessibilityManager,
|
||||
mHighPriorityProvider, mINotificationManager, mNotificationEntryManager,
|
||||
mHighPriorityProvider, mINotificationManager,
|
||||
mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager,
|
||||
mChannelEditorDialogController, mContextTracker, mAssistantFeedbackController,
|
||||
Optional.of(mBubblesManager), new UiEventLoggerFake(), mOnUserInteractionCallback,
|
||||
mShadeController, mock(DumpManager.class));
|
||||
mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
|
||||
mCheckSaveListener, mOnSettingsClickListener);
|
||||
mOnSettingsClickListener);
|
||||
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.OperatorNameViewController;
|
||||
import com.android.systemui.statusbar.PulseExpansionHandler;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
@@ -129,7 +128,6 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
@@ -220,7 +218,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
@Mock private BatteryController mBatteryController;
|
||||
@Mock private DeviceProvisionedController mDeviceProvisionedController;
|
||||
@Mock private StatusBarNotificationPresenter mNotificationPresenter;
|
||||
@Mock private NotificationFilter mNotificationFilter;
|
||||
@Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
|
||||
@Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
|
||||
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@@ -242,7 +239,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
@Mock private AutoHideController mAutoHideController;
|
||||
@Mock private StatusBarWindowController mStatusBarWindowController;
|
||||
@Mock private StatusBarWindowStateController mStatusBarWindowStateController;
|
||||
@Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
|
||||
@Mock private UserSwitcherController mUserSwitcherController;
|
||||
@Mock private Bubbles mBubbles;
|
||||
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
|
||||
@@ -283,7 +279,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
@Mock private OperatorNameViewController mOperatorNameViewController;
|
||||
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
|
||||
@Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
|
||||
@Mock private NotifPipelineFlags mNotifPipelineFlags;
|
||||
@Mock private NotifLiveDataStore mNotifLiveDataStore;
|
||||
@Mock private InteractionJankMonitor mJankMonitor;
|
||||
@Mock private DeviceStateManager mDeviceStateManager;
|
||||
@@ -298,7 +293,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
|
||||
|
||||
IPowerManager powerManagerService = mock(IPowerManager.class);
|
||||
IThermalService thermalService = mock(IThermalService.class);
|
||||
@@ -310,7 +304,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
mPowerManager,
|
||||
mDreamManager,
|
||||
mAmbientDisplayConfiguration,
|
||||
mNotificationFilter,
|
||||
mStatusBarStateController,
|
||||
mKeyguardStateController,
|
||||
mBatteryController,
|
||||
@@ -410,7 +403,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
mNotificationGutsManager,
|
||||
notificationLogger,
|
||||
mNotificationInterruptStateProvider,
|
||||
mNotificationViewHierarchyManager,
|
||||
new PanelExpansionStateManager(),
|
||||
mKeyguardViewMediator,
|
||||
new DisplayMetrics(),
|
||||
@@ -472,7 +464,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
mWallpaperManager,
|
||||
Optional.of(mStartingSurface),
|
||||
mActivityLaunchAnimator,
|
||||
mNotifPipelineFlags,
|
||||
mJankMonitor,
|
||||
mDeviceStateManager,
|
||||
mWiredChargingRippleController, mDreamManager);
|
||||
@@ -659,7 +650,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
public void testShouldHeadsUp_nonSuppressedGroupSummary() throws Exception {
|
||||
when(mPowerManager.isScreenOn()).thenReturn(true);
|
||||
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
|
||||
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
|
||||
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||
|
||||
Notification n = new Notification.Builder(getContext(), "a")
|
||||
@@ -683,7 +673,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
public void testShouldHeadsUp_suppressedGroupSummary() throws Exception {
|
||||
when(mPowerManager.isScreenOn()).thenReturn(true);
|
||||
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
|
||||
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
|
||||
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||
|
||||
Notification n = new Notification.Builder(getContext(), "a")
|
||||
@@ -707,7 +696,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
public void testShouldHeadsUp_suppressedHeadsUp() throws Exception {
|
||||
when(mPowerManager.isScreenOn()).thenReturn(true);
|
||||
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
|
||||
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
|
||||
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||
|
||||
Notification n = new Notification.Builder(getContext(), "a").build();
|
||||
@@ -729,7 +717,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
public void testShouldHeadsUp_noSuppressedHeadsUp() throws Exception {
|
||||
when(mPowerManager.isScreenOn()).thenReturn(true);
|
||||
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
|
||||
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
|
||||
when(mDreamManager.isDreaming()).thenReturn(false);
|
||||
|
||||
Notification n = new Notification.Builder(getContext(), "a").build();
|
||||
@@ -1041,7 +1028,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
PowerManager powerManager,
|
||||
IDreamManager dreamManager,
|
||||
AmbientDisplayConfiguration ambientDisplayConfiguration,
|
||||
NotificationFilter filter,
|
||||
StatusBarStateController controller,
|
||||
KeyguardStateController keyguardStateController,
|
||||
BatteryController batteryController,
|
||||
@@ -1055,7 +1041,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
||||
powerManager,
|
||||
dreamManager,
|
||||
ambientDisplayConfiguration,
|
||||
filter,
|
||||
batteryController,
|
||||
controller,
|
||||
keyguardStateController,
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shade.NotificationPanelViewController;
|
||||
import com.android.systemui.shade.NotificationShadeWindowView;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.shade.ShadeControllerImpl;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
@@ -51,7 +50,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
@@ -77,16 +75,17 @@ import org.mockito.ArgumentCaptor;
|
||||
@RunWithLooper()
|
||||
public class StatusBarNotificationPresenterTest extends SysuiTestCase {
|
||||
private StatusBarNotificationPresenter mStatusBarNotificationPresenter;
|
||||
private NotificationInterruptStateProvider mNotificationInterruptStateProvider =
|
||||
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider =
|
||||
mock(NotificationInterruptStateProvider.class);
|
||||
private NotificationInterruptSuppressor mInterruptSuppressor;
|
||||
private CommandQueue mCommandQueue;
|
||||
private FakeMetricsLogger mMetricsLogger;
|
||||
private ShadeController mShadeController = mock(ShadeController.class);
|
||||
private CentralSurfaces mCentralSurfaces = mock(CentralSurfaces.class);
|
||||
private KeyguardStateController mKeyguardStateController = mock(KeyguardStateController.class);
|
||||
private NotifPipelineFlags mNotifPipelineFlags = mock(NotifPipelineFlags.class);
|
||||
private InitController mInitController = new InitController();
|
||||
private final ShadeController mShadeController = mock(ShadeController.class);
|
||||
private final CentralSurfaces mCentralSurfaces = mock(CentralSurfaces.class);
|
||||
private final KeyguardStateController mKeyguardStateController =
|
||||
mock(KeyguardStateController.class);
|
||||
private final NotifPipelineFlags mNotifPipelineFlags = mock(NotifPipelineFlags.class);
|
||||
private final InitController mInitController = new InitController();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -117,16 +116,13 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
|
||||
mock(ActivityStarter.class),
|
||||
stackScrollLayoutController,
|
||||
mock(DozeScrimController.class),
|
||||
mock(ScrimController.class),
|
||||
mock(NotificationShadeWindowController.class),
|
||||
mock(DynamicPrivacyController.class),
|
||||
mKeyguardStateController,
|
||||
mock(KeyguardIndicationController.class),
|
||||
mCentralSurfaces,
|
||||
mock(ShadeControllerImpl.class),
|
||||
mock(LockscreenShadeTransitionController.class),
|
||||
mCommandQueue,
|
||||
mock(NotificationViewHierarchyManager.class),
|
||||
mock(NotificationLockscreenUserManager.class),
|
||||
mock(SysuiStatusBarStateController.class),
|
||||
mock(NotifShadeEventSource.class),
|
||||
|
||||
@@ -93,7 +93,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.RankingBuilder;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
@@ -319,7 +318,6 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mock(PowerManager.class),
|
||||
mock(IDreamManager.class),
|
||||
mock(AmbientDisplayConfiguration.class),
|
||||
mock(NotificationFilter.class),
|
||||
mock(StatusBarStateController.class),
|
||||
mock(KeyguardStateController.class),
|
||||
mock(BatteryController.class),
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.service.dreams.IDreamManager;
|
||||
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter;
|
||||
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
|
||||
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger;
|
||||
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
|
||||
@@ -40,7 +39,6 @@ public class TestableNotificationInterruptStateProviderImpl
|
||||
PowerManager powerManager,
|
||||
IDreamManager dreamManager,
|
||||
AmbientDisplayConfiguration ambientDisplayConfiguration,
|
||||
NotificationFilter filter,
|
||||
StatusBarStateController statusBarStateController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
BatteryController batteryController,
|
||||
@@ -53,7 +51,6 @@ public class TestableNotificationInterruptStateProviderImpl
|
||||
powerManager,
|
||||
dreamManager,
|
||||
ambientDisplayConfiguration,
|
||||
filter,
|
||||
batteryController,
|
||||
statusBarStateController,
|
||||
keyguardStateController,
|
||||
|
||||
Reference in New Issue
Block a user