Merge "Inline notif pipeline flag in NotifEntryManager" into tm-qpr-dev

This commit is contained in:
Steve Elliott
2022-08-01 23:39:25 +00:00
committed by Android (Google) Code Review
21 changed files with 25 additions and 1791 deletions

View File

@@ -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);

View File

@@ -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.
*/

View File

@@ -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;
}
}

View File

@@ -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.
*/

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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

View File

@@ -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));

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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));

View File

@@ -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() { }
}
}

View File

@@ -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")

View File

@@ -118,7 +118,6 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
mPowerManager,
mDreamManager,
mAmbientDisplayConfiguration,
mNotificationFilter,
mBatteryController,
mStatusBarStateController,
mKeyguardStateController,

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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),

View File

@@ -94,7 +94,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;
@@ -328,7 +327,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),

View File

@@ -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,