Move HighPriority variable out of Notif/ListEntry
Test: atest SystemUiTests Change-Id: Id69301091fc74cf0ff7136f8ccd51901f6c8017f
This commit is contained in:
@@ -24,7 +24,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a set of grouped notifications. The final notification list is usually a mix of
|
||||
@@ -58,22 +57,15 @@ public class GroupEntry extends ListEntry {
|
||||
|
||||
@VisibleForTesting
|
||||
public void setSummary(@Nullable NotificationEntry summary) {
|
||||
if (!Objects.equals(mSummary, summary)) {
|
||||
mSummary = summary;
|
||||
onGroupingUpdated();
|
||||
}
|
||||
mSummary = summary;
|
||||
}
|
||||
|
||||
void clearChildren() {
|
||||
if (mChildren.size() != 0) {
|
||||
mChildren.clear();
|
||||
onGroupingUpdated();
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
void addChild(NotificationEntry child) {
|
||||
mChildren.add(child);
|
||||
onGroupingUpdated();
|
||||
}
|
||||
|
||||
void sortChildren(Comparator<? super NotificationEntry> c) {
|
||||
|
||||
@@ -18,38 +18,20 @@ package com.android.systemui.statusbar.notification.collection;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.DerivedMember;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.IsHighPriorityProvider;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Abstract superclass for top-level entries, i.e. things that can appear in the final notification
|
||||
* list shown to users. In practice, this means either GroupEntries or NotificationEntries.
|
||||
*/
|
||||
public abstract class ListEntry {
|
||||
private final String mKey;
|
||||
private final IsHighPriorityProvider mIsHighPriorityProvider = new IsHighPriorityProvider();
|
||||
private final List<DerivedMember> mDerivedMemberList = Arrays.asList(mIsHighPriorityProvider);
|
||||
|
||||
@Nullable private GroupEntry mParent;
|
||||
@Nullable private GroupEntry mPreviousParent;
|
||||
private int mSection;
|
||||
int mFirstAddedIteration = -1;
|
||||
|
||||
// TODO: (b/145659174) remove groupManager when moving to NewNotifPipeline. Logic
|
||||
// replaced in GroupEntry and NotifListBuilderImpl
|
||||
private final NotificationGroupManager mGroupManager;
|
||||
|
||||
ListEntry(String key) {
|
||||
mKey = key;
|
||||
|
||||
// TODO: (b/145659174) remove
|
||||
mGroupManager = Dependency.get(NotificationGroupManager.class);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
@@ -68,11 +50,7 @@ public abstract class ListEntry {
|
||||
}
|
||||
|
||||
void setParent(@Nullable GroupEntry parent) {
|
||||
if (!Objects.equals(mParent, parent)) {
|
||||
invalidateParent();
|
||||
mParent = parent;
|
||||
onGroupingUpdated();
|
||||
}
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
@Nullable public GroupEntry getPreviousParent() {
|
||||
@@ -91,58 +69,4 @@ public abstract class ListEntry {
|
||||
void setSection(int section) {
|
||||
mSection = section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the cached values of DerivedMembers.
|
||||
*/
|
||||
void invalidateDerivedMembers() {
|
||||
for (int i = 0; i < mDerivedMemberList.size(); i++) {
|
||||
mDerivedMemberList.get(i).invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this notification is shown to the user as a high priority notification: visible on
|
||||
* the lock screen/status bar and in the top section in the shade.
|
||||
*/
|
||||
public boolean isHighPriority() {
|
||||
return mIsHighPriorityProvider.get(this);
|
||||
}
|
||||
|
||||
private void invalidateParent() {
|
||||
// invalidate our parent (GroupEntry) since DerivedMembers may be dependent on children
|
||||
if (getParent() != null) {
|
||||
getParent().invalidateDerivedMembers();
|
||||
}
|
||||
|
||||
// TODO: (b/145659174) remove
|
||||
final NotificationEntry notifEntry = getRepresentativeEntry();
|
||||
if (notifEntry != null && mGroupManager.isGroupChild(notifEntry.getSbn())) {
|
||||
NotificationEntry summary = mGroupManager.getLogicalGroupSummary(notifEntry.getSbn());
|
||||
if (summary != null) {
|
||||
summary.invalidateDerivedMembers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onGroupingUpdated() {
|
||||
for (int i = 0; i < mDerivedMemberList.size(); i++) {
|
||||
mDerivedMemberList.get(i).onGroupingUpdated();
|
||||
}
|
||||
invalidateParent();
|
||||
}
|
||||
|
||||
void onSbnUpdated() {
|
||||
for (int i = 0; i < mDerivedMemberList.size(); i++) {
|
||||
mDerivedMemberList.get(i).onSbnUpdated();
|
||||
}
|
||||
invalidateParent();
|
||||
}
|
||||
|
||||
void onRankingUpdated() {
|
||||
for (int i = 0; i < mDerivedMemberList.size(); i++) {
|
||||
mDerivedMemberList.get(i).onRankingUpdated();
|
||||
}
|
||||
invalidateParent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,11 +204,8 @@ public final class NotificationEntry extends ListEntry {
|
||||
+ " doesn't match existing key " + mKey);
|
||||
}
|
||||
|
||||
if (!Objects.equals(mSbn, sbn)) {
|
||||
mSbn = sbn;
|
||||
mBubbleMetadata = mSbn.getNotification().getBubbleMetadata();
|
||||
onSbnUpdated();
|
||||
}
|
||||
mSbn = sbn;
|
||||
mBubbleMetadata = mSbn.getNotification().getBubbleMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,10 +230,7 @@ public final class NotificationEntry extends ListEntry {
|
||||
+ " doesn't match existing key " + mKey);
|
||||
}
|
||||
|
||||
if (!Objects.equals(mRanking, ranking)) {
|
||||
mRanking = ranking;
|
||||
onRankingUpdated();
|
||||
}
|
||||
mRanking = ranking;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.service.notification.StatusBarNotification
|
||||
import com.android.systemui.statusbar.NotificationMediaManager
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
|
||||
import com.android.systemui.statusbar.notification.logging.NotifEvent
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
|
||||
@@ -54,7 +55,8 @@ open class NotificationRankingManager @Inject constructor(
|
||||
private val notifFilter: NotificationFilter,
|
||||
private val notifLog: NotifLog,
|
||||
sectionsFeatureManager: NotificationSectionsFeatureManager,
|
||||
private val peopleNotificationIdentifier: PeopleNotificationIdentifier
|
||||
private val peopleNotificationIdentifier: PeopleNotificationIdentifier,
|
||||
private val highPriorityProvider: HighPriorityProvider
|
||||
) {
|
||||
|
||||
var rankingMap: RankingMap? = null
|
||||
@@ -81,6 +83,9 @@ open class NotificationRankingManager @Inject constructor(
|
||||
val aHeadsUp = a.isRowHeadsUp
|
||||
val bHeadsUp = b.isRowHeadsUp
|
||||
|
||||
val aIsHighPriority = a.isHighPriority()
|
||||
val bIsHighPriority = b.isHighPriority()
|
||||
|
||||
when {
|
||||
usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1
|
||||
aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1
|
||||
@@ -90,8 +95,8 @@ open class NotificationRankingManager @Inject constructor(
|
||||
aMedia != bMedia -> if (aMedia) -1 else 1
|
||||
// Upsort PRIORITY_MAX system notifications
|
||||
aSystemMax != bSystemMax -> if (aSystemMax) -1 else 1
|
||||
a.isHighPriority != b.isHighPriority ->
|
||||
-1 * a.isHighPriority.compareTo(b.isHighPriority)
|
||||
aIsHighPriority != bIsHighPriority ->
|
||||
-1 * aIsHighPriority.compareTo(bIsHighPriority)
|
||||
aRank != bRank -> aRank - bRank
|
||||
else -> nb.notification.`when`.compareTo(na.notification.`when`)
|
||||
}
|
||||
@@ -154,7 +159,7 @@ open class NotificationRankingManager @Inject constructor(
|
||||
) {
|
||||
if (usePeopleFiltering && entry.isPeopleNotification()) {
|
||||
entry.bucket = BUCKET_PEOPLE
|
||||
} else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority) {
|
||||
} else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority()) {
|
||||
entry.bucket = BUCKET_ALERTING
|
||||
} else {
|
||||
entry.bucket = BUCKET_SILENT
|
||||
@@ -178,10 +183,6 @@ open class NotificationRankingManager @Inject constructor(
|
||||
// TODO: notify group manager here?
|
||||
groupManager.onEntryUpdated(entry, oldSbn)
|
||||
}
|
||||
|
||||
// TODO: (b/145659174) remove after moving to new NotifPipeline
|
||||
// (should be able to remove all groupManager code post-migration)
|
||||
entry.invalidateDerivedMembers()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,6 +192,9 @@ open class NotificationRankingManager @Inject constructor(
|
||||
sbn.isPeopleNotification()
|
||||
private fun StatusBarNotification.isPeopleNotification() =
|
||||
peopleNotificationIdentifier.isPeopleNotification(this)
|
||||
|
||||
private fun NotificationEntry.isHighPriority() =
|
||||
highPriorityProvider.isHighPriority(this)
|
||||
}
|
||||
|
||||
// Convenience functions
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.notification.collection.NotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -62,6 +63,7 @@ public class KeyguardCoordinator implements Coordinator {
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final HighPriorityProvider mHighPriorityProvider;
|
||||
|
||||
@Inject
|
||||
public KeyguardCoordinator(
|
||||
@@ -71,15 +73,16 @@ public class KeyguardCoordinator implements Coordinator {
|
||||
NotificationLockscreenUserManager lockscreenUserManager,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
StatusBarStateController statusBarStateController,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor) {
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
HighPriorityProvider highPriorityProvider) {
|
||||
mContext = context;
|
||||
mMainHandler = mainThreadHandler;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mLockscreenUserManager = lockscreenUserManager;
|
||||
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mHighPriorityProvider = highPriorityProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,7 +154,7 @@ public class KeyguardCoordinator implements Coordinator {
|
||||
}
|
||||
if (NotificationUtils.useNewInterruptionModel(mContext)
|
||||
&& hideSilentNotificationsOnLockscreen()) {
|
||||
return entry.isHighPriority();
|
||||
return mHighPriorityProvider.isHighPriority(entry);
|
||||
} else {
|
||||
return entry.getRepresentativeEntry() != null
|
||||
&& !entry.getRepresentativeEntry().getRanking().isAmbient();
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.provider;
|
||||
/**
|
||||
* Caches a computed value until invalidate() is called
|
||||
* @param <Parent> Object used to computeValue
|
||||
* @param <Value> type of value to cache until invalidate is called
|
||||
*/
|
||||
public abstract class DerivedMember<Parent, Value> {
|
||||
private Value mValue;
|
||||
protected abstract Value computeValue(Parent parent);
|
||||
|
||||
/**
|
||||
* Gets the last cached value, else recomputes the value.
|
||||
*/
|
||||
public Value get(Parent parent) {
|
||||
if (mValue == null) {
|
||||
mValue = computeValue(parent);
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the cached value.
|
||||
* Next time "get" is called, the value is recomputed.
|
||||
*/
|
||||
public void invalidate() {
|
||||
mValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a NotificationEntry's status bar notification has updated.
|
||||
* Derived members can invalidate here.
|
||||
*/
|
||||
public void onSbnUpdated() {}
|
||||
|
||||
/**
|
||||
* Called when a NotificationEntry's Ranking has updated.
|
||||
* Derived members can invalidate here.
|
||||
*/
|
||||
public void onRankingUpdated() {}
|
||||
|
||||
/**
|
||||
* Called when a ListEntry's grouping information (parent or children) has changed.
|
||||
* Derived members can invalidate here.
|
||||
*/
|
||||
public void onGroupingUpdated() {}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.provider;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
|
||||
import com.android.systemui.statusbar.notification.collection.GroupEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Determines whether a notification is considered 'high priority'.
|
||||
*
|
||||
* Notifications that are high priority are visible on the lock screen/status bar and in the top
|
||||
* section in the shade.
|
||||
*/
|
||||
@Singleton
|
||||
public class HighPriorityProvider {
|
||||
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
|
||||
@Inject
|
||||
public HighPriorityProvider(PeopleNotificationIdentifier peopleNotificationIdentifier) {
|
||||
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the ListEntry is high priority, else false
|
||||
*
|
||||
* A NotificationEntry is considered high priority if it:
|
||||
* - has importance greater than or equal to IMPORTANCE_DEFAULT
|
||||
* OR
|
||||
* - their importance has NOT been set to a low priority option by the user AND the
|
||||
* notification fulfills one of the following:
|
||||
* - has a person associated with it
|
||||
* - has a media session associated with it
|
||||
* - has messaging style
|
||||
*
|
||||
* A GroupEntry is considered high priority if its representativeEntry (summary) or children are
|
||||
* high priority
|
||||
*/
|
||||
public boolean isHighPriority(ListEntry entry) {
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final NotificationEntry notifEntry = entry.getRepresentativeEntry();
|
||||
return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
|
||||
|| hasHighPriorityCharacteristics(notifEntry)
|
||||
|| hasHighPriorityChild(entry);
|
||||
}
|
||||
|
||||
|
||||
private boolean hasHighPriorityChild(ListEntry entry) {
|
||||
if (entry instanceof GroupEntry) {
|
||||
for (NotificationEntry child : ((GroupEntry) entry).getChildren()) {
|
||||
if (isHighPriority(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasHighPriorityCharacteristics(NotificationEntry entry) {
|
||||
return !hasUserSetImportance(entry)
|
||||
&& (isImportantOngoing(entry)
|
||||
|| entry.getSbn().getNotification().hasMediaSession()
|
||||
|| isPeopleNotification(entry)
|
||||
|| isMessagingStyle(entry));
|
||||
}
|
||||
|
||||
private boolean isImportantOngoing(NotificationEntry entry) {
|
||||
return entry.getSbn().getNotification().isForegroundService()
|
||||
&& entry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_LOW;
|
||||
}
|
||||
|
||||
private boolean isMessagingStyle(NotificationEntry entry) {
|
||||
return Notification.MessagingStyle.class.equals(
|
||||
entry.getSbn().getNotification().getNotificationStyle());
|
||||
}
|
||||
|
||||
private boolean isPeopleNotification(NotificationEntry entry) {
|
||||
return mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn());
|
||||
}
|
||||
|
||||
private boolean hasUserSetImportance(NotificationEntry entry) {
|
||||
return entry.getRanking().getChannel() != null
|
||||
&& entry.getRanking().getChannel().hasUserSetImportance();
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.provider;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Person;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.statusbar.notification.collection.GroupEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Whether the ListEntry is shown to the user as a high priority notification: visible on
|
||||
* the lock screen/status bar and in the top section in the shade.
|
||||
*
|
||||
* A NotificationEntry is considered high priority if it:
|
||||
* - has importance greater than or equal to IMPORTANCE_DEFAULT
|
||||
* OR
|
||||
* - their importance has NOT been set to a low priority option by the user AND the notification
|
||||
* fulfills one of the following:
|
||||
* - has a person associated with it
|
||||
* - has a media session associated with it
|
||||
* - has messaging style
|
||||
*
|
||||
* A GroupEntry is considered high priority if its representativeEntry (summary) or children are
|
||||
* high priority
|
||||
*/
|
||||
public class IsHighPriorityProvider extends DerivedMember<ListEntry, Boolean> {
|
||||
// TODO: (b/145659174) remove groupManager when moving to NewNotifPipeline. Logic
|
||||
// replaced in GroupEntry and NotifListBuilderImpl
|
||||
private final NotificationGroupManager mGroupManager;
|
||||
|
||||
|
||||
public IsHighPriorityProvider() {
|
||||
// TODO: (b/145659174) remove
|
||||
mGroupManager = Dependency.get(NotificationGroupManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean computeValue(ListEntry entry) {
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isHighPriority(entry);
|
||||
}
|
||||
|
||||
private boolean isHighPriority(ListEntry listEntry) {
|
||||
// requires groups have been set (AFTER PipelineState.STATE_TRANSFORMING)
|
||||
final NotificationEntry notifEntry = listEntry.getRepresentativeEntry();
|
||||
return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
|
||||
|| hasHighPriorityCharacteristics(notifEntry)
|
||||
|| hasHighPriorityChild(listEntry);
|
||||
|
||||
}
|
||||
|
||||
private boolean hasHighPriorityChild(ListEntry entry) {
|
||||
// TODO: (b/145659174) remove
|
||||
if (entry instanceof NotificationEntry) {
|
||||
NotificationEntry notifEntry = (NotificationEntry) entry;
|
||||
if (mGroupManager.isSummaryOfGroup(notifEntry.getSbn())) {
|
||||
List<NotificationEntry> logicalChildren =
|
||||
mGroupManager.getLogicalChildren(notifEntry.getSbn());
|
||||
for (NotificationEntry child : logicalChildren) {
|
||||
if (child.isHighPriority()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry instanceof GroupEntry) {
|
||||
for (NotificationEntry child : ((GroupEntry) entry).getChildren()) {
|
||||
if (child.isHighPriority()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasHighPriorityCharacteristics(NotificationEntry entry) {
|
||||
return !hasUserSetImportance(entry)
|
||||
&& (isImportantOngoing(entry)
|
||||
|| entry.getSbn().getNotification().hasMediaSession()
|
||||
|| hasPerson(entry)
|
||||
|| isMessagingStyle(entry));
|
||||
}
|
||||
|
||||
private boolean isImportantOngoing(NotificationEntry entry) {
|
||||
return entry.getSbn().getNotification().isForegroundService()
|
||||
&& entry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_LOW;
|
||||
}
|
||||
|
||||
private boolean isMessagingStyle(NotificationEntry entry) {
|
||||
return Notification.MessagingStyle.class.equals(
|
||||
entry.getSbn().getNotification().getNotificationStyle());
|
||||
}
|
||||
|
||||
private boolean hasPerson(NotificationEntry entry) {
|
||||
// TODO: cache favorite and recent contacts to check contact affinity
|
||||
Notification notification = entry.getSbn().getNotification();
|
||||
ArrayList<Person> people = notification.extras != null
|
||||
? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)
|
||||
: new ArrayList<>();
|
||||
return people != null && !people.isEmpty();
|
||||
}
|
||||
|
||||
private boolean hasUserSetImportance(NotificationEntry entry) {
|
||||
return entry.getRanking().getChannel() != null
|
||||
&& entry.getRanking().getChannel().hasUserSetImportance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSbnUpdated() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRankingUpdated() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGroupingUpdated() {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
@@ -81,6 +82,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
private final Context mContext;
|
||||
private final VisualStabilityManager mVisualStabilityManager;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
private final HighPriorityProvider mHighPriorityProvider;
|
||||
|
||||
// Dependencies:
|
||||
private final NotificationLockscreenUserManager mLockscreenUserManager =
|
||||
@@ -109,12 +111,14 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
@Inject
|
||||
public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager,
|
||||
Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler,
|
||||
AccessibilityManager accessibilityManager) {
|
||||
AccessibilityManager accessibilityManager,
|
||||
HighPriorityProvider highPriorityProvider) {
|
||||
mContext = context;
|
||||
mVisualStabilityManager = visualStabilityManager;
|
||||
mStatusBarLazy = statusBarLazy;
|
||||
mMainHandler = mainHandler;
|
||||
mAccessibilityManager = accessibilityManager;
|
||||
mHighPriorityProvider = highPriorityProvider;
|
||||
}
|
||||
|
||||
public void setUpWithPresenter(NotificationPresenter presenter,
|
||||
@@ -331,8 +335,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
|
||||
row.getIsNonblockable(),
|
||||
isForBlockingHelper,
|
||||
row.getEntry().getImportance(),
|
||||
row.getEntry().isHighPriority());
|
||||
|
||||
mHighPriorityProvider.isHighPriority(row.getEntry()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.statusbar.AlphaOptimizedImageView;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -269,7 +270,8 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
|
||||
}
|
||||
mAppOpsItem = createAppOpsItem(mContext);
|
||||
if (mIsUsingBidirectionalSwipe) {
|
||||
mInfoItem = createInfoItem(mContext, !mParent.getEntry().isHighPriority());
|
||||
mInfoItem = createInfoItem(mContext,
|
||||
mParent.getEntry().getBucket() == NotificationSectionsManager.BUCKET_SILENT);
|
||||
} else {
|
||||
mInfoItem = createInfoItem(mContext);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
@@ -233,7 +234,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
|
||||
mock(NotificationFilter.class),
|
||||
mNotifLog,
|
||||
mock(NotificationSectionsFeatureManager.class),
|
||||
mock(PeopleNotificationIdentifier.class)),
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class)),
|
||||
mEnvironment,
|
||||
mFeatureFlags
|
||||
);
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.RankingBuilder;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class GroupEntryTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testIsHighPriority_addChild() {
|
||||
// GIVEN a GroupEntry with a lowPrioritySummary and no children
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
final NotificationEntry lowPrioritySummary = createNotifEntry(false);
|
||||
setSummary(parentEntry, lowPrioritySummary);
|
||||
assertFalse(parentEntry.isHighPriority());
|
||||
|
||||
// WHEN we add a high priority child and invalidate derived members
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
parentEntry.invalidateDerivedMembers();
|
||||
|
||||
// THEN the GroupEntry's priority is updated to high even though the summary is still low
|
||||
// priority
|
||||
assertTrue(parentEntry.isHighPriority());
|
||||
assertFalse(lowPrioritySummary.isHighPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_clearChildren() {
|
||||
// GIVEN a GroupEntry with a lowPrioritySummary and high priority children
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
setSummary(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
assertTrue(parentEntry.isHighPriority());
|
||||
|
||||
// WHEN we clear the children and invalidate derived members
|
||||
parentEntry.clearChildren();
|
||||
parentEntry.invalidateDerivedMembers();
|
||||
|
||||
// THEN the parentEntry isn't high priority anymore
|
||||
assertFalse(parentEntry.isHighPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_summaryUpdated() {
|
||||
// GIVEN a GroupEntry with a lowPrioritySummary and no children
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
final NotificationEntry lowPrioritySummary = createNotifEntry(false);
|
||||
setSummary(parentEntry, lowPrioritySummary);
|
||||
assertFalse(parentEntry.isHighPriority());
|
||||
|
||||
// WHEN the summary changes to high priority and invalidates its derived members
|
||||
lowPrioritySummary.setRanking(
|
||||
new RankingBuilder()
|
||||
.setKey(lowPrioritySummary.getKey())
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build());
|
||||
lowPrioritySummary.invalidateDerivedMembers();
|
||||
assertTrue(lowPrioritySummary.isHighPriority());
|
||||
|
||||
// THEN the GroupEntry's priority is updated to high
|
||||
assertTrue(parentEntry.isHighPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_checkChildrenToCalculatePriority() {
|
||||
// GIVEN:
|
||||
// GroupEntry = parentEntry, summary = lowPrioritySummary
|
||||
// NotificationEntry = lowPriorityChild
|
||||
// NotificationEntry = highPriorityChild
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
setSummary(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
|
||||
// THEN the GroupEntry parentEntry is high priority since it has a high priority child
|
||||
assertTrue(parentEntry.isHighPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_childEntryRankingUpdated() {
|
||||
// GIVEN:
|
||||
// GroupEntry = parentEntry, summary = lowPrioritySummary
|
||||
// NotificationEntry = lowPriorityChild
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
final NotificationEntry lowPriorityChild = createNotifEntry(false);
|
||||
setSummary(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, lowPriorityChild);
|
||||
|
||||
// WHEN the child entry ranking changes to high priority and invalidates its derived members
|
||||
lowPriorityChild.setRanking(
|
||||
new RankingBuilder()
|
||||
.setKey(lowPriorityChild.getKey())
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build());
|
||||
lowPriorityChild.invalidateDerivedMembers();
|
||||
|
||||
// THEN the parent entry's high priority value is updated - but not the parent's summary
|
||||
assertTrue(parentEntry.isHighPriority());
|
||||
assertFalse(parentEntry.getSummary().isHighPriority());
|
||||
}
|
||||
|
||||
private NotificationEntry createNotifEntry(boolean highPriority) {
|
||||
return new NotificationEntryBuilder()
|
||||
.setImportance(highPriority ? IMPORTANCE_HIGH : IMPORTANCE_MIN)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void setSummary(GroupEntry parent, NotificationEntry summary) {
|
||||
parent.setSummary(summary);
|
||||
summary.setParent(parent);
|
||||
}
|
||||
|
||||
private void addChild(GroupEntry parent, NotificationEntry child) {
|
||||
parent.addChild(child);
|
||||
child.setParent(parent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.RankingBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class HighPriorityProviderTest extends SysuiTestCase {
|
||||
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
private HighPriorityProvider mHighPriorityProvider;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mHighPriorityProvider = new HighPriorityProvider(mPeopleNotificationIdentifier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highImportance() {
|
||||
// GIVEN notification has high importance
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false);
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peopleNotification() {
|
||||
// GIVEN notification is low importance and is a people notification
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.build();
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_LOW)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(true);
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messagingStyle() {
|
||||
// GIVEN notification is low importance but has messaging style
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false);
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowImportanceForeground() {
|
||||
// GIVEN notification is low importance and is associated with a foreground service
|
||||
final Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_LOW)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false);
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minImportanceForeground() {
|
||||
// GIVEN notification is low importance and is associated with a foreground service
|
||||
final Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_MIN)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false);
|
||||
|
||||
// THEN it does NOT have high priority
|
||||
assertFalse(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userChangeTrumpsHighPriorityCharacteristics() {
|
||||
// GIVEN notification has high priority characteristics but the user changed the importance
|
||||
// to less than IMPORTANCE_DEFAULT (ie: IMPORTANCE_LOW or IMPORTANCE_MIN)
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
|
||||
.build();
|
||||
final NotificationChannel channel = new NotificationChannel("a", "a",
|
||||
IMPORTANCE_LOW);
|
||||
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setChannel(channel)
|
||||
.build();
|
||||
when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(true);
|
||||
|
||||
// THEN it does NOT have high priority
|
||||
assertFalse(mHighPriorityProvider.isHighPriority(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_summaryUpdated() {
|
||||
// GIVEN a GroupEntry with a lowPrioritySummary and no children
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
final NotificationEntry lowPrioritySummary = createNotifEntry(false);
|
||||
setSummary(parentEntry, lowPrioritySummary);
|
||||
assertFalse(mHighPriorityProvider.isHighPriority(parentEntry));
|
||||
|
||||
// WHEN the summary changes to high priority
|
||||
lowPrioritySummary.setRanking(
|
||||
new RankingBuilder()
|
||||
.setKey(lowPrioritySummary.getKey())
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build());
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(lowPrioritySummary));
|
||||
|
||||
// THEN the GroupEntry's priority is updated to high
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_checkChildrenToCalculatePriority() {
|
||||
// GIVEN:
|
||||
// GroupEntry = parentEntry, summary = lowPrioritySummary
|
||||
// NotificationEntry = lowPriorityChild
|
||||
// NotificationEntry = highPriorityChild
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
setSummary(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, createNotifEntry(true));
|
||||
|
||||
// THEN the GroupEntry parentEntry is high priority since it has a high priority child
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_childEntryRankingUpdated() {
|
||||
// GIVEN:
|
||||
// GroupEntry = parentEntry, summary = lowPrioritySummary
|
||||
// NotificationEntry = lowPriorityChild
|
||||
final GroupEntry parentEntry = new GroupEntry("test_group_key");
|
||||
final NotificationEntry lowPriorityChild = createNotifEntry(false);
|
||||
setSummary(parentEntry, createNotifEntry(false));
|
||||
addChild(parentEntry, lowPriorityChild);
|
||||
|
||||
// WHEN the child entry ranking changes to high priority
|
||||
lowPriorityChild.setRanking(
|
||||
new RankingBuilder()
|
||||
.setKey(lowPriorityChild.getKey())
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build());
|
||||
|
||||
// THEN the parent entry's high priority value is updated - but not the parent's summary
|
||||
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
|
||||
assertFalse(mHighPriorityProvider.isHighPriority(parentEntry.getSummary()));
|
||||
}
|
||||
|
||||
private NotificationEntry createNotifEntry(boolean highPriority) {
|
||||
return new NotificationEntryBuilder()
|
||||
.setImportance(highPriority ? IMPORTANCE_HIGH : IMPORTANCE_MIN)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void setSummary(GroupEntry parent, NotificationEntry summary) {
|
||||
parent.setSummary(summary);
|
||||
summary.setParent(parent);
|
||||
}
|
||||
|
||||
private void addChild(GroupEntry parent, NotificationEntry child) {
|
||||
parent.addChild(child);
|
||||
child.setParent(parent);
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import static android.app.Notification.CATEGORY_CALL;
|
||||
import static android.app.Notification.CATEGORY_EVENT;
|
||||
import static android.app.Notification.CATEGORY_MESSAGE;
|
||||
import static android.app.Notification.CATEGORY_REMINDER;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
|
||||
|
||||
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
|
||||
@@ -91,44 +89,6 @@ public class NotificationEntryTest extends SysuiTestCase {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsHighPriority_notificationUpdates() {
|
||||
// GIVEN a notification with high importance
|
||||
final NotificationEntry entryHigh = new NotificationEntryBuilder()
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build();
|
||||
|
||||
// WHEN we get the value for the high priority entry, we're caching the high priority value
|
||||
assertTrue(entryHigh.isHighPriority());
|
||||
|
||||
// WHEN we change the ranking and derived members (high priority) are invalidated
|
||||
entryHigh.setRanking(
|
||||
new RankingBuilder()
|
||||
.setKey(entryHigh.getKey())
|
||||
.setImportance(IMPORTANCE_MIN)
|
||||
.build());
|
||||
entryHigh.invalidateDerivedMembers();
|
||||
|
||||
// THEN the priority is recalculated and is now low
|
||||
assertFalse(entryHigh.isHighPriority());
|
||||
|
||||
// WHEN the sbn is updated to have messaging style (high priority characteristic)
|
||||
// AND the entry invalidates its derived members
|
||||
final Notification notification =
|
||||
new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
final StatusBarNotification sbn = entryHigh.getSbn();
|
||||
entryHigh.setSbn(new StatusBarNotification(
|
||||
sbn.getPackageName(), sbn.getPackageName(),
|
||||
sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
|
||||
notification, sbn.getUser(), sbn.getOverrideGroupKey(), 0));
|
||||
entryHigh.invalidateDerivedMembers();
|
||||
|
||||
// THEN the priority is recalculated and is now high
|
||||
assertTrue(entryHigh.isHighPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsExemptFromDndVisualSuppression_foreground() {
|
||||
mEntry.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
|
||||
import com.android.systemui.statusbar.NotificationMediaManager
|
||||
import com.android.systemui.statusbar.notification.NotificationFilter
|
||||
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
|
||||
@@ -62,7 +63,8 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
mock(NotificationFilter::class.java),
|
||||
mock(NotifLog::class.java),
|
||||
mock(NotificationSectionsFeatureManager::class.java),
|
||||
personNotificationIdentifier
|
||||
personNotificationIdentifier,
|
||||
HighPriorityProvider(personNotificationIdentifier)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -182,7 +184,8 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
filter: NotificationFilter,
|
||||
notifLog: NotifLog,
|
||||
sectionsFeatureManager: NotificationSectionsFeatureManager,
|
||||
peopleNotificationIdentifier: PeopleNotificationIdentifier
|
||||
peopleNotificationIdentifier: PeopleNotificationIdentifier,
|
||||
highPriorityProvider: HighPriorityProvider
|
||||
) : NotificationRankingManager(
|
||||
mediaManager,
|
||||
groupManager,
|
||||
@@ -190,7 +193,8 @@ class NotificationRankingManagerTest : SysuiTestCase() {
|
||||
filter,
|
||||
notifLog,
|
||||
sectionsFeatureManager,
|
||||
peopleNotificationIdentifier
|
||||
peopleNotificationIdentifier,
|
||||
highPriorityProvider
|
||||
) {
|
||||
fun applyTestRankingMap(r: RankingMap) {
|
||||
rankingMap = r
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.android.systemui.statusbar.notification.collection.NotifListBuilderIm
|
||||
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.NotifFilter;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -66,6 +67,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
|
||||
@Mock private BroadcastDispatcher mBroadcastDispatcher;
|
||||
@Mock private StatusBarStateController mStatusBarStateController;
|
||||
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock private HighPriorityProvider mHighPriorityProvider;
|
||||
@Mock private NotifListBuilderImpl mNotifListBuilder;
|
||||
|
||||
private NotificationEntry mEntry;
|
||||
@@ -78,7 +80,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
|
||||
mKeyguardCoordinator = new KeyguardCoordinator(
|
||||
mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager,
|
||||
mBroadcastDispatcher, mStatusBarStateController,
|
||||
mKeyguardUpdateMonitor);
|
||||
mKeyguardUpdateMonitor, mHighPriorityProvider);
|
||||
|
||||
mEntry = new NotificationEntryBuilder()
|
||||
.setUser(new UserHandle(NOTIF_USER_ID))
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.provider;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.Person;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class IsHighPriorityProviderTest extends SysuiTestCase {
|
||||
private IsHighPriorityProvider mIsHighPriorityProvider;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mIsHighPriorityProvider = new IsHighPriorityProvider();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCache() {
|
||||
// GIVEN a notification with high importance
|
||||
final NotificationEntry entryHigh = new NotificationEntryBuilder()
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build();
|
||||
|
||||
// GIVEN notification with min importance
|
||||
final NotificationEntry entryMin = new NotificationEntryBuilder()
|
||||
.setImportance(IMPORTANCE_MIN)
|
||||
.build();
|
||||
|
||||
// WHEN we get the value for the high priority entry
|
||||
assertTrue(mIsHighPriorityProvider.get(entryHigh));
|
||||
|
||||
// THEN the value is cached, so even when passed an entryMin, we still get high priority
|
||||
assertTrue(mIsHighPriorityProvider.get(entryMin));
|
||||
|
||||
// UNTIL the provider is invalidated
|
||||
mIsHighPriorityProvider.invalidate();
|
||||
|
||||
// THEN the priority is recalculated
|
||||
assertFalse(mIsHighPriorityProvider.get(entryMin));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highImportance() {
|
||||
// GIVEN notification has high importance
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setImportance(IMPORTANCE_HIGH)
|
||||
.build();
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peopleNotification() {
|
||||
// GIVEN notification is low importance but has a person associated with it
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.addPerson(
|
||||
new Person.Builder()
|
||||
.setName("name")
|
||||
.setKey("abc")
|
||||
.setUri("uri")
|
||||
.setBot(true)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_LOW)
|
||||
.build();
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messagingStyle() {
|
||||
// GIVEN notification is low importance but has messaging style
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.build();
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lowImportanceForeground() {
|
||||
// GIVEN notification is low importance and is associated with a foreground service
|
||||
final Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_LOW)
|
||||
.build();
|
||||
|
||||
// THEN it has high priority
|
||||
assertTrue(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minImportanceForeground() {
|
||||
// GIVEN notification is low importance and is associated with a foreground service
|
||||
final Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setImportance(IMPORTANCE_MIN)
|
||||
.build();
|
||||
|
||||
// THEN it does NOT have high priority
|
||||
assertFalse(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userChangeTrumpsHighPriorityCharacteristics() {
|
||||
// GIVEN notification has high priority characteristics but the user changed the importance
|
||||
// to less than IMPORTANCE_DEFAULT (ie: IMPORTANCE_LOW or IMPORTANCE_MIN)
|
||||
final Notification notification = new Notification.Builder(mContext, "test")
|
||||
.addPerson(
|
||||
new Person.Builder()
|
||||
.setName("name")
|
||||
.setKey("abc")
|
||||
.setUri("uri")
|
||||
.setBot(true)
|
||||
.build())
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
|
||||
.build();
|
||||
|
||||
final NotificationChannel channel = new NotificationChannel("a", "a",
|
||||
IMPORTANCE_LOW);
|
||||
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
|
||||
final NotificationEntry entry = new NotificationEntryBuilder()
|
||||
.setNotification(notification)
|
||||
.setChannel(channel)
|
||||
.build();
|
||||
|
||||
// THEN it does NOT have high priority
|
||||
assertFalse(mIsHighPriorityProvider.get(entry));
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ import com.android.systemui.statusbar.NotificationTestHelper;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
@@ -113,6 +114,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
@Mock private DeviceProvisionedController mDeviceProvisionedController;
|
||||
@Mock private StatusBar mStatusBar;
|
||||
@Mock private AccessibilityManager mAccessibilityManager;
|
||||
@Mock private HighPriorityProvider mHighPriorityProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -128,7 +130,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
|
||||
|
||||
mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
|
||||
() -> mStatusBar, mHandler, mAccessibilityManager);
|
||||
() -> mStatusBar, mHandler, mAccessibilityManager, mHighPriorityProvider);
|
||||
mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
|
||||
mCheckSaveListener, mOnSettingsClickListener);
|
||||
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
|
||||
@@ -391,6 +393,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
|
||||
.build();
|
||||
|
||||
when(row.getIsNonblockable()).thenReturn(false);
|
||||
when(mHighPriorityProvider.isHighPriority(entry)).thenReturn(true);
|
||||
StatusBarNotification statusBarNotification = entry.getSbn();
|
||||
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
|
||||
|
||||
|
||||
@@ -267,8 +267,6 @@ public class NotificationSectionsManagerTest extends SysuiTestCase {
|
||||
ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class,
|
||||
RETURNS_DEEP_STUBS);
|
||||
when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
|
||||
when(notifRow.getEntry().isHighPriority())
|
||||
.thenReturn(children[i] == ChildType.HIPRI);
|
||||
when(notifRow.getEntry().getBucket()).thenReturn(
|
||||
children[i] == ChildType.HIPRI ? BUCKET_ALERTING : BUCKET_SILENT);
|
||||
when(notifRow.getParent()).thenReturn(mNssl);
|
||||
|
||||
@@ -71,6 +71,7 @@ import com.android.systemui.statusbar.notification.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
|
||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||
import com.android.systemui.statusbar.notification.logging.NotifLog;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
|
||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||
@@ -165,7 +166,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
||||
mock(NotificationFilter.class),
|
||||
mock(NotifLog.class),
|
||||
mock(NotificationSectionsFeatureManager.class),
|
||||
mock(PeopleNotificationIdentifier.class)
|
||||
mock(PeopleNotificationIdentifier.class),
|
||||
mock(HighPriorityProvider.class)
|
||||
),
|
||||
mock(NotificationEntryManager.KeyguardEnvironment.class),
|
||||
mock(FeatureFlags.class));
|
||||
|
||||
Reference in New Issue
Block a user