Merge "Isolating important conversations" into rvc-dev am: 822b72843d am: ac09b9168e
Change-Id: I5137c82673513f902fcf68b9da4f4eb84b1625d1
This commit is contained in:
@@ -177,12 +177,32 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
currentUserId);
|
currentUserId);
|
||||||
ent.setSensitive(sensitive, deviceSensitive);
|
ent.setSensitive(sensitive, deviceSensitive);
|
||||||
ent.getRow().setNeedsRedaction(needsRedaction);
|
ent.getRow().setNeedsRedaction(needsRedaction);
|
||||||
if (mGroupManager.isChildInGroupWithSummary(ent.getSbn())) {
|
boolean isChildInGroup = mGroupManager.isChildInGroupWithSummary(ent.getSbn());
|
||||||
NotificationEntry summary = mGroupManager.getGroupSummary(ent.getSbn());
|
|
||||||
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(summary);
|
boolean groupChangesAllowed = mVisualStabilityManager.areGroupChangesAllowed()
|
||||||
|
|| !ent.hasFinishedInitialization();
|
||||||
|
NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
|
||||||
|
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);
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChildInGroup) {
|
||||||
|
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent);
|
||||||
if (orderedChildren == null) {
|
if (orderedChildren == null) {
|
||||||
orderedChildren = new ArrayList<>();
|
orderedChildren = new ArrayList<>();
|
||||||
mTmpChildOrderMap.put(summary, orderedChildren);
|
mTmpChildOrderMap.put(parent, orderedChildren);
|
||||||
}
|
}
|
||||||
orderedChildren.add(ent);
|
orderedChildren.add(ent);
|
||||||
} else {
|
} else {
|
||||||
@@ -205,7 +225,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
|
for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
|
||||||
if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getEntry().getSbn())) {
|
if (mEntryManager.getPendingOrActiveNotif(viewToRemove.getEntry().getKey()) != null) {
|
||||||
// we are only transferring this notification to its parent, don't generate an
|
// we are only transferring this notification to its parent, don't generate an
|
||||||
// animation
|
// animation
|
||||||
mListContainer.setChildTransferInProgress(true);
|
mListContainer.setChildTransferInProgress(true);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.android.internal.widget.ConversationLayout
|
|||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||||
import com.android.systemui.statusbar.notification.row.NotificationContentView
|
import com.android.systemui.statusbar.notification.row.NotificationContentView
|
||||||
|
import com.android.systemui.statusbar.phone.NotificationGroupManager
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@@ -60,6 +61,7 @@ class ConversationNotificationProcessor @Inject constructor(
|
|||||||
@Singleton
|
@Singleton
|
||||||
class ConversationNotificationManager @Inject constructor(
|
class ConversationNotificationManager @Inject constructor(
|
||||||
private val notificationEntryManager: NotificationEntryManager,
|
private val notificationEntryManager: NotificationEntryManager,
|
||||||
|
private val notificationGroupManager: NotificationGroupManager,
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) {
|
) {
|
||||||
// Need this state to be thread safe, since it's accessed from the ui thread
|
// Need this state to be thread safe, since it's accessed from the ui thread
|
||||||
@@ -81,10 +83,19 @@ class ConversationNotificationManager @Inject constructor(
|
|||||||
if (rankingMap.getRanking(entry.sbn.key, ranking) &&
|
if (rankingMap.getRanking(entry.sbn.key, ranking) &&
|
||||||
ranking.isConversation) {
|
ranking.isConversation) {
|
||||||
val important = ranking.channel.isImportantConversation
|
val important = ranking.channel.isImportantConversation
|
||||||
|
var changed = false
|
||||||
entry.row?.layouts?.asSequence()
|
entry.row?.layouts?.asSequence()
|
||||||
?.flatMap(::getLayouts)
|
?.flatMap(::getLayouts)
|
||||||
?.mapNotNull { it as? ConversationLayout }
|
?.mapNotNull { it as? ConversationLayout }
|
||||||
?.forEach { it.setIsImportantConversation(important) }
|
?.forEach {
|
||||||
|
if (important != it.isImportantConversation) {
|
||||||
|
it.setIsImportantConversation(important)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
notificationGroupManager.updateIsolation(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ public class NotificationEntryManager implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReorderingAllowed() {
|
public void onChangeAllowed() {
|
||||||
updateNotifications("reordering is now allowed");
|
updateNotifications("reordering is now allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,14 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
|
|
||||||
private static final long TEMPORARY_REORDERING_ALLOWED_DURATION = 1000;
|
private static final long TEMPORARY_REORDERING_ALLOWED_DURATION = 1000;
|
||||||
|
|
||||||
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
|
private final ArrayList<Callback> mReorderingAllowedCallbacks = new ArrayList<>();
|
||||||
|
private final ArrayList<Callback> mGroupChangesAllowedCallbacks = new ArrayList<>();
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
|
|
||||||
private boolean mPanelExpanded;
|
private boolean mPanelExpanded;
|
||||||
private boolean mScreenOn;
|
private boolean mScreenOn;
|
||||||
private boolean mReorderingAllowed;
|
private boolean mReorderingAllowed;
|
||||||
|
private boolean mGroupChangedAllowed;
|
||||||
private boolean mIsTemporaryReorderingAllowed;
|
private boolean mIsTemporaryReorderingAllowed;
|
||||||
private long mTemporaryReorderingStart;
|
private long mTemporaryReorderingStart;
|
||||||
private VisibilityLocationProvider mVisibilityLocationProvider;
|
private VisibilityLocationProvider mVisibilityLocationProvider;
|
||||||
@@ -83,13 +85,22 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a callback to invoke when reordering is allowed again.
|
* Add a callback to invoke when reordering is allowed again.
|
||||||
* @param callback
|
|
||||||
*/
|
*/
|
||||||
public void addReorderingAllowedCallback(Callback callback) {
|
public void addReorderingAllowedCallback(Callback callback) {
|
||||||
if (mCallbacks.contains(callback)) {
|
if (mReorderingAllowedCallbacks.contains(callback)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCallbacks.add(callback);
|
mReorderingAllowedCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to invoke when group changes are allowed again.
|
||||||
|
*/
|
||||||
|
public void addGroupChangesAllowedCallback(Callback callback) {
|
||||||
|
if (mGroupChangesAllowedCallbacks.contains(callback)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mGroupChangesAllowedCallbacks.add(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,7 +108,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
*/
|
*/
|
||||||
public void setPanelExpanded(boolean expanded) {
|
public void setPanelExpanded(boolean expanded) {
|
||||||
mPanelExpanded = expanded;
|
mPanelExpanded = expanded;
|
||||||
updateReorderingAllowed();
|
updateAllowedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +116,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
*/
|
*/
|
||||||
public void setScreenOn(boolean screenOn) {
|
public void setScreenOn(boolean screenOn) {
|
||||||
mScreenOn = screenOn;
|
mScreenOn = screenOn;
|
||||||
updateReorderingAllowed();
|
updateAllowedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,25 +127,30 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mPulsing = pulsing;
|
mPulsing = pulsing;
|
||||||
updateReorderingAllowed();
|
updateAllowedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateReorderingAllowed() {
|
private void updateAllowedStates() {
|
||||||
boolean reorderingAllowed =
|
boolean reorderingAllowed =
|
||||||
(!mScreenOn || !mPanelExpanded || mIsTemporaryReorderingAllowed) && !mPulsing;
|
(!mScreenOn || !mPanelExpanded || mIsTemporaryReorderingAllowed) && !mPulsing;
|
||||||
boolean changedToTrue = reorderingAllowed && !mReorderingAllowed;
|
boolean changedToTrue = reorderingAllowed && !mReorderingAllowed;
|
||||||
mReorderingAllowed = reorderingAllowed;
|
mReorderingAllowed = reorderingAllowed;
|
||||||
if (changedToTrue) {
|
if (changedToTrue) {
|
||||||
notifyCallbacks();
|
notifyChangeAllowed(mReorderingAllowedCallbacks);
|
||||||
|
}
|
||||||
|
boolean groupChangesAllowed = (!mScreenOn || !mPanelExpanded) && !mPulsing;
|
||||||
|
changedToTrue = groupChangesAllowed && !mGroupChangedAllowed;
|
||||||
|
mGroupChangedAllowed = groupChangesAllowed;
|
||||||
|
if (changedToTrue) {
|
||||||
|
notifyChangeAllowed(mGroupChangesAllowedCallbacks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyCallbacks() {
|
private void notifyChangeAllowed(ArrayList<Callback> callbacks) {
|
||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < callbacks.size(); i++) {
|
||||||
Callback callback = mCallbacks.get(i);
|
callbacks.get(i).onChangeAllowed();
|
||||||
callback.onReorderingAllowed();
|
|
||||||
}
|
}
|
||||||
mCallbacks.clear();
|
callbacks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,6 +160,13 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
return mReorderingAllowed;
|
return mReorderingAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether changes in the grouping should be allowed right now.
|
||||||
|
*/
|
||||||
|
public boolean areGroupChangesAllowed() {
|
||||||
|
return mGroupChangedAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether a specific notification is allowed to reorder. Certain notifications are
|
* @return whether a specific notification is allowed to reorder. Certain notifications are
|
||||||
* allowed to reorder even if {@link #isReorderingAllowed()} returns false, like newly added
|
* allowed to reorder even if {@link #isReorderingAllowed()} returns false, like newly added
|
||||||
@@ -197,12 +220,12 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
mTemporaryReorderingStart = SystemClock.elapsedRealtime();
|
mTemporaryReorderingStart = SystemClock.elapsedRealtime();
|
||||||
}
|
}
|
||||||
mIsTemporaryReorderingAllowed = true;
|
mIsTemporaryReorderingAllowed = true;
|
||||||
updateReorderingAllowed();
|
updateAllowedStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Runnable mOnTemporaryReorderingExpired = () -> {
|
private final Runnable mOnTemporaryReorderingExpired = () -> {
|
||||||
mIsTemporaryReorderingAllowed = false;
|
mIsTemporaryReorderingAllowed = false;
|
||||||
updateReorderingAllowed();
|
updateAllowedStates();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,9 +252,9 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
|
|||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
/**
|
/**
|
||||||
* Called when reordering is allowed again.
|
* Called when changing is allowed again.
|
||||||
*/
|
*/
|
||||||
void onReorderingAllowed();
|
void onChangeAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
*/
|
*/
|
||||||
public EditedSuggestionInfo editedSuggestionInfo;
|
public EditedSuggestionInfo editedSuggestionInfo;
|
||||||
|
|
||||||
private NotificationEntry parent; // our parent (if we're in a group)
|
|
||||||
private ExpandableNotificationRow row; // the outer expanded view
|
private ExpandableNotificationRow row; // the outer expanded view
|
||||||
private ExpandableNotificationRowController mRowController;
|
private ExpandableNotificationRowController mRowController;
|
||||||
|
|
||||||
@@ -710,7 +709,7 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChildInGroup() {
|
public boolean isChildInGroup() {
|
||||||
return parent == null;
|
return row != null && row.isChildInGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.collection.coordinator
|
||||||
|
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A coordinator that elevates important conversation notifications
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
class ConversationCoordinator @Inject constructor() : Coordinator {
|
||||||
|
|
||||||
|
private val notificationPromoter = object : NotifPromoter(TAG) {
|
||||||
|
override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean {
|
||||||
|
return entry.channel?.isImportantConversation == true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun attach(pipeline: NotifPipeline) {
|
||||||
|
pipeline.addPromoter(notificationPromoter)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "ConversationCoordinator"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,7 @@ public class NotifCoordinators implements Dumpable {
|
|||||||
DeviceProvisionedCoordinator deviceProvisionedCoordinator,
|
DeviceProvisionedCoordinator deviceProvisionedCoordinator,
|
||||||
BubbleCoordinator bubbleCoordinator,
|
BubbleCoordinator bubbleCoordinator,
|
||||||
HeadsUpCoordinator headsUpCoordinator,
|
HeadsUpCoordinator headsUpCoordinator,
|
||||||
|
ConversationCoordinator conversationCoordinator,
|
||||||
PreparationCoordinator preparationCoordinator) {
|
PreparationCoordinator preparationCoordinator) {
|
||||||
dumpManager.registerDumpable(TAG, this);
|
dumpManager.registerDumpable(TAG, this);
|
||||||
mCoordinators.add(new HideLocallyDismissedNotifsCoordinator());
|
mCoordinators.add(new HideLocallyDismissedNotifsCoordinator());
|
||||||
@@ -66,6 +67,7 @@ public class NotifCoordinators implements Dumpable {
|
|||||||
mCoordinators.add(deviceProvisionedCoordinator);
|
mCoordinators.add(deviceProvisionedCoordinator);
|
||||||
mCoordinators.add(bubbleCoordinator);
|
mCoordinators.add(bubbleCoordinator);
|
||||||
if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
|
if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
|
||||||
|
mCoordinators.add(conversationCoordinator);
|
||||||
mCoordinators.add(headsUpCoordinator);
|
mCoordinators.add(headsUpCoordinator);
|
||||||
mCoordinators.add(preparationCoordinator);
|
mCoordinators.add(preparationCoordinator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class PeopleNotificationIdentifierImpl @Inject constructor(
|
|||||||
return TYPE_NON_PERSON
|
return TYPE_NON_PERSON
|
||||||
}
|
}
|
||||||
|
|
||||||
val childTypes = groupManager.getLogicalChildren(statusBarNotification)
|
val childTypes = groupManager.getChildren(statusBarNotification)
|
||||||
?.asSequence()
|
?.asSequence()
|
||||||
?.map { getPeopleNotificationType(it.sbn, it.ranking) }
|
?.map { getPeopleNotificationType(it.sbn, it.ranking) }
|
||||||
?: return TYPE_NON_PERSON
|
?: return TYPE_NON_PERSON
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import static android.app.Notification.EXTRA_IS_GROUP_CONVERSATION;
|
|||||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||||
import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
|
|
||||||
|
|
||||||
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
|
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
|
||||||
|
|
||||||
@@ -44,7 +43,6 @@ import android.os.Handler;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.transition.ChangeBounds;
|
import android.transition.ChangeBounds;
|
||||||
@@ -56,15 +54,12 @@ import android.util.Log;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.settingslib.notification.ConversationIconFactory;
|
import com.android.settingslib.notification.ConversationIconFactory;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||||
@@ -517,7 +512,6 @@ public class NotificationConversationInfo extends LinearLayout implements
|
|||||||
bgHandler.post(
|
bgHandler.post(
|
||||||
new UpdateChannelRunnable(mINotificationManager, mPackageName,
|
new UpdateChannelRunnable(mINotificationManager, mPackageName,
|
||||||
mAppUid, mSelectedAction, mNotificationChannel));
|
mAppUid, mSelectedAction, mNotificationChannel));
|
||||||
mVisualStabilityManager.temporarilyAllowReordering();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
|
|||||||
// VisualStabilityManager.Callback overrides:
|
// VisualStabilityManager.Callback overrides:
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReorderingAllowed() {
|
public void onChangeAllowed() {
|
||||||
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
|
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
|
||||||
for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
|
for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
|
||||||
if (isAlerting(entry.getKey())) {
|
if (isAlerting(entry.getKey())) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -85,6 +86,17 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
return group.expanded;
|
return group.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if the group that this notification is associated with logically is expanded
|
||||||
|
*/
|
||||||
|
public boolean isLogicalGroupExpanded(StatusBarNotification sbn) {
|
||||||
|
NotificationGroup group = mGroupMap.get(sbn.getGroupKey());
|
||||||
|
if (group == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return group.expanded;
|
||||||
|
}
|
||||||
|
|
||||||
public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) {
|
public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) {
|
||||||
NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
|
NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
@@ -147,7 +159,15 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the group manager that a new entry was added
|
||||||
|
*/
|
||||||
public void onEntryAdded(final NotificationEntry added) {
|
public void onEntryAdded(final NotificationEntry added) {
|
||||||
|
updateIsolation(added);
|
||||||
|
onEntryAddedInternal(added);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEntryAddedInternal(final NotificationEntry added) {
|
||||||
if (added.isRowRemoved()) {
|
if (added.isRowRemoved()) {
|
||||||
added.setDebugThrowable(new Throwable());
|
added.setDebugThrowable(new Throwable());
|
||||||
}
|
}
|
||||||
@@ -193,9 +213,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onEntryBecomingChild(NotificationEntry entry) {
|
private void onEntryBecomingChild(NotificationEntry entry) {
|
||||||
if (shouldIsolate(entry)) {
|
updateIsolation(entry);
|
||||||
isolateNotification(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSuppression(NotificationGroup group) {
|
private void updateSuppression(NotificationGroup group) {
|
||||||
@@ -242,15 +260,6 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationEntry getIsolatedChild(String groupKey) {
|
|
||||||
for (StatusBarNotification sbn : mIsolatedEntries.values()) {
|
|
||||||
if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn.getKey())) {
|
|
||||||
return mGroupMap.get(sbn.getKey()).summary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update an entry's group information
|
* Update an entry's group information
|
||||||
* @param entry notification entry to update
|
* @param entry notification entry to update
|
||||||
@@ -278,7 +287,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) {
|
if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) {
|
||||||
onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary);
|
onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary);
|
||||||
}
|
}
|
||||||
onEntryAdded(entry);
|
onEntryAddedInternal(entry);
|
||||||
mIsUpdatingUnchangedGroup = false;
|
mIsUpdatingUnchangedGroup = false;
|
||||||
if (isIsolated(entry.getSbn().getKey())) {
|
if (isIsolated(entry.getSbn().getKey())) {
|
||||||
mIsolatedEntries.put(entry.getKey(), entry.getSbn());
|
mIsolatedEntries.put(entry.getKey(), entry.getSbn());
|
||||||
@@ -413,13 +422,28 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ArrayList<NotificationEntry> children = new ArrayList<>(group.children.values());
|
ArrayList<NotificationEntry> children = new ArrayList<>(group.children.values());
|
||||||
NotificationEntry isolatedChild = getIsolatedChild(summary.getGroupKey());
|
for (StatusBarNotification sbn : mIsolatedEntries.values()) {
|
||||||
if (isolatedChild != null) {
|
if (sbn.getGroupKey().equals(summary.getGroupKey())) {
|
||||||
children.add(isolatedChild);
|
children.add(mGroupMap.get(sbn.getKey()).summary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the children that are in the summary's group, not including those isolated.
|
||||||
|
*
|
||||||
|
* @param summary summary of a group
|
||||||
|
* @return list of the children
|
||||||
|
*/
|
||||||
|
public @Nullable ArrayList<NotificationEntry> getChildren(StatusBarNotification summary) {
|
||||||
|
NotificationGroup group = mGroupMap.get(summary.getGroupKey());
|
||||||
|
if (group == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new ArrayList<>(group.children.values());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there is a {@link NotificationGroup} associated with the provided entry, this method
|
* If there is a {@link NotificationGroup} associated with the provided entry, this method
|
||||||
* will update the suppression of that group.
|
* will update the suppression of that group.
|
||||||
@@ -495,17 +519,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
|
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
|
||||||
onAlertStateChanged(entry, isHeadsUp);
|
updateIsolation(entry);
|
||||||
}
|
|
||||||
|
|
||||||
private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting) {
|
|
||||||
if (isAlerting) {
|
|
||||||
if (shouldIsolate(entry)) {
|
|
||||||
isolateNotification(entry);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stopIsolatingNotification(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -519,13 +533,17 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
|
|
||||||
private boolean shouldIsolate(NotificationEntry entry) {
|
private boolean shouldIsolate(NotificationEntry entry) {
|
||||||
StatusBarNotification sbn = entry.getSbn();
|
StatusBarNotification sbn = entry.getSbn();
|
||||||
NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
|
|
||||||
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
|
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
NotificationChannel channel = entry.getChannel();
|
||||||
|
if (channel != null && channel.isImportantConversation()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
|
if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
|
||||||
return (sbn.getNotification().fullScreenIntent != null
|
return (sbn.getNotification().fullScreenIntent != null
|
||||||
|| notificationGroup == null
|
|| notificationGroup == null
|
||||||
|| !notificationGroup.expanded
|
|| !notificationGroup.expanded
|
||||||
@@ -545,7 +563,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
|
|
||||||
mIsolatedEntries.put(sbn.getKey(), sbn);
|
mIsolatedEntries.put(sbn.getKey(), sbn);
|
||||||
|
|
||||||
onEntryAdded(entry);
|
onEntryAddedInternal(entry);
|
||||||
// We also need to update the suppression of the old group, because this call comes
|
// We also need to update the suppression of the old group, because this call comes
|
||||||
// even before the groupManager knows about the notification at all.
|
// even before the groupManager knows about the notification at all.
|
||||||
// When the notification gets added afterwards it is already isolated and therefore
|
// When the notification gets added afterwards it is already isolated and therefore
|
||||||
@@ -556,6 +574,20 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the isolation of an entry, splitting it from the group.
|
||||||
|
*/
|
||||||
|
public void updateIsolation(NotificationEntry entry) {
|
||||||
|
boolean isIsolated = isIsolated(entry.getSbn().getKey());
|
||||||
|
if (shouldIsolate(entry)) {
|
||||||
|
if (!isIsolated) {
|
||||||
|
isolateNotification(entry);
|
||||||
|
}
|
||||||
|
} else if (isIsolated) {
|
||||||
|
stopIsolatingNotification(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop isolating a notification and re-group it with its original logical group.
|
* Stop isolating a notification and re-group it with its original logical group.
|
||||||
*
|
*
|
||||||
@@ -563,11 +595,11 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|
|||||||
*/
|
*/
|
||||||
private void stopIsolatingNotification(NotificationEntry entry) {
|
private void stopIsolatingNotification(NotificationEntry entry) {
|
||||||
StatusBarNotification sbn = entry.getSbn();
|
StatusBarNotification sbn = entry.getSbn();
|
||||||
if (mIsolatedEntries.containsKey(sbn.getKey())) {
|
if (isIsolated(sbn.getKey())) {
|
||||||
// not isolated anymore, we need to update the groups
|
// not isolated anymore, we need to update the groups
|
||||||
onEntryRemovedInternal(entry, entry.getSbn());
|
onEntryRemovedInternal(entry, entry.getSbn());
|
||||||
mIsolatedEntries.remove(sbn.getKey());
|
mIsolatedEntries.remove(sbn.getKey());
|
||||||
onEntryAdded(entry);
|
onEntryAddedInternal(entry);
|
||||||
for (OnGroupChangeListener listener : mListeners) {
|
for (OnGroupChangeListener listener : mListeners) {
|
||||||
listener.onGroupsChanged();
|
listener.onGroupsChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager);
|
mLockscreenUserManager);
|
||||||
mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
|
mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
|
||||||
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
|
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
|
||||||
|
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
|
||||||
|
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
|
||||||
|
|
||||||
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
|
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.setScreenOn(true);
|
mVisualStabilityManager.setScreenOn(true);
|
||||||
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
||||||
mVisualStabilityManager.setScreenOn(false);
|
mVisualStabilityManager.setScreenOn(false);
|
||||||
verify(mCallback).onReorderingAllowed();
|
verify(mCallback).onChangeAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -119,7 +119,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.setScreenOn(true);
|
mVisualStabilityManager.setScreenOn(true);
|
||||||
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
||||||
mVisualStabilityManager.setPanelExpanded(false);
|
mVisualStabilityManager.setPanelExpanded(false);
|
||||||
verify(mCallback).onReorderingAllowed();
|
verify(mCallback).onChangeAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -130,7 +130,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.setScreenOn(false);
|
mVisualStabilityManager.setScreenOn(false);
|
||||||
mVisualStabilityManager.setScreenOn(true);
|
mVisualStabilityManager.setScreenOn(true);
|
||||||
mVisualStabilityManager.setScreenOn(false);
|
mVisualStabilityManager.setScreenOn(false);
|
||||||
verify(mCallback).onReorderingAllowed();
|
verify(mCallback).onChangeAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -190,7 +190,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.setPulsing(true);
|
mVisualStabilityManager.setPulsing(true);
|
||||||
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
|
||||||
mVisualStabilityManager.setPulsing(false);
|
mVisualStabilityManager.setPulsing(false);
|
||||||
verify(mCallback).onReorderingAllowed();
|
verify(mCallback).onChangeAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -204,7 +204,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.temporarilyAllowReordering();
|
mVisualStabilityManager.temporarilyAllowReordering();
|
||||||
|
|
||||||
// THEN callbacks are notified that reordering is allowed
|
// THEN callbacks are notified that reordering is allowed
|
||||||
verify(mCallback).onReorderingAllowed();
|
verify(mCallback).onChangeAllowed();
|
||||||
assertTrue(mVisualStabilityManager.isReorderingAllowed());
|
assertTrue(mVisualStabilityManager.isReorderingAllowed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase {
|
|||||||
mVisualStabilityManager.temporarilyAllowReordering();
|
mVisualStabilityManager.temporarilyAllowReordering();
|
||||||
|
|
||||||
// THEN reordering is still not allowed
|
// THEN reordering is still not allowed
|
||||||
verify(mCallback, never()).onReorderingAllowed();
|
verify(mCallback, never()).onChangeAllowed();
|
||||||
assertFalse(mVisualStabilityManager.isReorderingAllowed());
|
assertFalse(mVisualStabilityManager.isReorderingAllowed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.collection.coordinator
|
||||||
|
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
||||||
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
class ConversationCoordinatorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private var coordinator: ConversationCoordinator = ConversationCoordinator()
|
||||||
|
|
||||||
|
// captured listeners and pluggables:
|
||||||
|
private var promoter: NotifPromoter? = null
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private val pipeline: NotifPipeline? = null
|
||||||
|
@Mock
|
||||||
|
private val channel: NotificationChannel? = null
|
||||||
|
private var entry: NotificationEntry? = null
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
whenever(channel!!.isImportantConversation).thenReturn(true)
|
||||||
|
|
||||||
|
coordinator.attach(pipeline!!)
|
||||||
|
|
||||||
|
// capture arguments:
|
||||||
|
val notifPromoterCaptor = ArgumentCaptor.forClass(NotifPromoter::class.java)
|
||||||
|
verify(pipeline).addPromoter(notifPromoterCaptor.capture())
|
||||||
|
promoter = notifPromoterCaptor.value
|
||||||
|
|
||||||
|
entry = NotificationEntryBuilder().setChannel(channel).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPromotesCurrentHUN() {
|
||||||
|
|
||||||
|
// only promote important conversations
|
||||||
|
assertTrue(promoter!!.shouldPromoteToTopLevel(entry))
|
||||||
|
assertFalse(promoter!!.shouldPromoteToTopLevel(NotificationEntryBuilder().build()))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -816,29 +816,4 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
|
|||||||
verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
|
verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
|
||||||
anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
|
anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAdjustImportanceTemporarilyAllowsReordering() {
|
|
||||||
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
|
|
||||||
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
|
|
||||||
mNotificationInfo.bindNotification(
|
|
||||||
mShortcutManager,
|
|
||||||
mMockPackageManager,
|
|
||||||
mMockINotificationManager,
|
|
||||||
mVisualStabilityManager,
|
|
||||||
TEST_PACKAGE_NAME,
|
|
||||||
mNotificationChannel,
|
|
||||||
mEntry,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
mIconFactory,
|
|
||||||
true);
|
|
||||||
|
|
||||||
mNotificationInfo.findViewById(R.id.silence).performClick();
|
|
||||||
mNotificationInfo.findViewById(R.id.done).performClick();
|
|
||||||
|
|
||||||
mTestableLooper.processAllMessages();
|
|
||||||
|
|
||||||
verify(mVisualStabilityManager).temporarilyAllowReordering();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6227,7 +6227,7 @@ public class NotificationManagerService extends SystemService {
|
|||||||
cancelNotificationLocked(
|
cancelNotificationLocked(
|
||||||
r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
|
r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
|
||||||
cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
|
cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
|
||||||
mSendDelete, childrenFlagChecker);
|
mSendDelete, childrenFlagChecker, mReason);
|
||||||
updateLightsLocked();
|
updateLightsLocked();
|
||||||
if (mShortcutHelper != null) {
|
if (mShortcutHelper != null) {
|
||||||
mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
|
mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
|
||||||
@@ -6687,7 +6687,7 @@ public class NotificationManagerService extends SystemService {
|
|||||||
// notification was a summary and its group key changed.
|
// notification was a summary and its group key changed.
|
||||||
if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) {
|
if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) {
|
||||||
cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */,
|
cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */,
|
||||||
null);
|
null, REASON_APP_CANCEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7892,7 +7892,7 @@ public class NotificationManagerService extends SystemService {
|
|||||||
final int M = canceledNotifications.size();
|
final int M = canceledNotifications.size();
|
||||||
for (int i = 0; i < M; i++) {
|
for (int i = 0; i < M; i++) {
|
||||||
cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
|
cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
|
||||||
listenerName, false /* sendDelete */, flagChecker);
|
listenerName, false /* sendDelete */, flagChecker, reason);
|
||||||
}
|
}
|
||||||
updateLightsLocked();
|
updateLightsLocked();
|
||||||
}
|
}
|
||||||
@@ -7963,7 +7963,7 @@ public class NotificationManagerService extends SystemService {
|
|||||||
// Warning: The caller is responsible for invoking updateLightsLocked().
|
// Warning: The caller is responsible for invoking updateLightsLocked().
|
||||||
@GuardedBy("mNotificationLock")
|
@GuardedBy("mNotificationLock")
|
||||||
private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
|
private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
|
||||||
String listenerName, boolean sendDelete, FlagChecker flagChecker) {
|
String listenerName, boolean sendDelete, FlagChecker flagChecker, int reason) {
|
||||||
Notification n = r.getNotification();
|
Notification n = r.getNotification();
|
||||||
if (!n.isGroupSummary()) {
|
if (!n.isGroupSummary()) {
|
||||||
return;
|
return;
|
||||||
@@ -7977,30 +7977,33 @@ public class NotificationManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancelGroupChildrenByListLocked(mNotificationList, r, callingUid, callingPid, listenerName,
|
cancelGroupChildrenByListLocked(mNotificationList, r, callingUid, callingPid, listenerName,
|
||||||
sendDelete, true, flagChecker);
|
sendDelete, true, flagChecker, reason);
|
||||||
cancelGroupChildrenByListLocked(mEnqueuedNotifications, r, callingUid, callingPid,
|
cancelGroupChildrenByListLocked(mEnqueuedNotifications, r, callingUid, callingPid,
|
||||||
listenerName, sendDelete, false, flagChecker);
|
listenerName, sendDelete, false, flagChecker, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mNotificationLock")
|
@GuardedBy("mNotificationLock")
|
||||||
private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList,
|
private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList,
|
||||||
NotificationRecord parentNotification, int callingUid, int callingPid,
|
NotificationRecord parentNotification, int callingUid, int callingPid,
|
||||||
String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker) {
|
String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker,
|
||||||
|
int reason) {
|
||||||
final String pkg = parentNotification.getSbn().getPackageName();
|
final String pkg = parentNotification.getSbn().getPackageName();
|
||||||
final int userId = parentNotification.getUserId();
|
final int userId = parentNotification.getUserId();
|
||||||
final int reason = REASON_GROUP_SUMMARY_CANCELED;
|
final int childReason = REASON_GROUP_SUMMARY_CANCELED;
|
||||||
for (int i = notificationList.size() - 1; i >= 0; i--) {
|
for (int i = notificationList.size() - 1; i >= 0; i--) {
|
||||||
final NotificationRecord childR = notificationList.get(i);
|
final NotificationRecord childR = notificationList.get(i);
|
||||||
final StatusBarNotification childSbn = childR.getSbn();
|
final StatusBarNotification childSbn = childR.getSbn();
|
||||||
if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) &&
|
if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) &&
|
||||||
childR.getGroupKey().equals(parentNotification.getGroupKey())
|
childR.getGroupKey().equals(parentNotification.getGroupKey())
|
||||||
&& (childR.getFlags() & FLAG_FOREGROUND_SERVICE) == 0
|
&& (childR.getFlags() & FLAG_FOREGROUND_SERVICE) == 0
|
||||||
&& (flagChecker == null || flagChecker.apply(childR.getFlags()))) {
|
&& (flagChecker == null || flagChecker.apply(childR.getFlags()))
|
||||||
|
&& (!childR.getChannel().isImportantConversation()
|
||||||
|
|| reason != REASON_CANCEL)) {
|
||||||
EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
|
EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
|
||||||
childSbn.getTag(), userId, 0, 0, reason, listenerName);
|
childSbn.getTag(), userId, 0, 0, childReason, listenerName);
|
||||||
notificationList.remove(i);
|
notificationList.remove(i);
|
||||||
mNotificationsByKey.remove(childR.getKey());
|
mNotificationsByKey.remove(childR.getKey());
|
||||||
cancelNotificationLocked(childR, sendDelete, reason, wasPosted, listenerName);
|
cancelNotificationLocked(childR, sendDelete, childReason, wasPosted, listenerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user