diff options
| author | 2020-01-16 22:23:08 +0000 | |
|---|---|---|
| committer | 2020-01-16 22:23:08 +0000 | |
| commit | 3bd8c209b10b3ecf81feb763af3047e960ff7853 (patch) | |
| tree | c98dacf401a9039eab13a2f5326b189de262ec14 | |
| parent | 5115b1aee3206cb78679b87764c81a29651a0185 (diff) | |
| parent | dcd70d6ec62e1e18215b624883b6f7ba17998be2 (diff) | |
Merge "Allow conversations to be demoted out of the conversation space"
11 files changed, 106 insertions, 23 deletions
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index bdc7b992421a..78f9cc8eaa62 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -105,6 +105,7 @@ public final class NotificationChannel implements Parcelable { private static final String ATT_ORIG_IMP = "orig_imp"; private static final String ATT_PARENT_CHANNEL = "parent"; private static final String ATT_CONVERSATION_ID = "conv_id"; + private static final String ATT_DEMOTE = "dem"; private static final String DELIMITER = ","; /** @@ -194,6 +195,7 @@ public final class NotificationChannel implements Parcelable { private boolean mImportanceLockedDefaultApp; private String mParentId = null; private String mConversationId = null; + private boolean mDemoted = false; /** * Creates a notification channel. @@ -260,6 +262,7 @@ public final class NotificationChannel implements Parcelable { mOriginalImportance = in.readInt(); mParentId = in.readString(); mConversationId = in.readString(); + mDemoted = in.readBoolean(); } @Override @@ -317,6 +320,7 @@ public final class NotificationChannel implements Parcelable { dest.writeInt(mOriginalImportance); dest.writeString(mParentId); dest.writeString(mConversationId); + dest.writeBoolean(mDemoted); } /** @@ -386,8 +390,6 @@ public final class NotificationChannel implements Parcelable { return input; } - // Modifiable by apps on channel creation. - /** * @hide */ @@ -395,6 +397,8 @@ public final class NotificationChannel implements Parcelable { mId = id; } + // Modifiable by apps on channel creation. + /** * Sets what group this channel belongs to. * @@ -767,6 +771,20 @@ public final class NotificationChannel implements Parcelable { } /** + * @hide + */ + public void setDemoted(boolean demoted) { + mDemoted = demoted; + } + + /** + * @hide + */ + public boolean isDemoted() { + return mDemoted; + } + + /** * Returns whether the user has chosen the importance of this channel, either to affirm the * initial selection from the app, or changed it to be higher or lower. * @see #getImportance() @@ -829,6 +847,7 @@ public final class NotificationChannel implements Parcelable { setOriginalImportance(safeInt(parser, ATT_ORIG_IMP, DEFAULT_IMPORTANCE)); setConversationId(parser.getAttributeValue(null, ATT_PARENT_CHANNEL), parser.getAttributeValue(null, ATT_CONVERSATION_ID)); + setDemoted(safeBool(parser, ATT_DEMOTE, false)); } @Nullable @@ -959,6 +978,9 @@ public final class NotificationChannel implements Parcelable { if (getConversationId() != null) { out.attribute(null, ATT_CONVERSATION_ID, getConversationId()); } + if (isDemoted()) { + out.attribute(null, ATT_DEMOTE, Boolean.toString(isDemoted())); + } // mImportanceLockedDefaultApp and mImportanceLockedByOEM have a different source of // truth and so aren't written to this xml file @@ -1118,7 +1140,8 @@ public final class NotificationChannel implements Parcelable { && mImportanceLockedDefaultApp == that.mImportanceLockedDefaultApp && mOriginalImportance == that.mOriginalImportance && Objects.equals(getParentChannelId(), that.getParentChannelId()) - && Objects.equals(getConversationId(), that.getConversationId()); + && Objects.equals(getConversationId(), that.getConversationId()) + && isDemoted() == that.isDemoted(); } @Override @@ -1129,7 +1152,7 @@ public final class NotificationChannel implements Parcelable { isFgServiceShown(), mVibrationEnabled, mShowBadge, isDeleted(), getGroup(), getAudioAttributes(), isBlockableSystem(), mAllowBubbles, mImportanceLockedByOEM, mImportanceLockedDefaultApp, mOriginalImportance, - mParentId, mConversationId); + mParentId, mConversationId, mDemoted); result = 31 * result + Arrays.hashCode(mVibration); return result; } @@ -1176,7 +1199,8 @@ public final class NotificationChannel implements Parcelable { + ", mImportanceLockedDefaultApp=" + mImportanceLockedDefaultApp + ", mOriginalImp=" + mOriginalImportance + ", mParent=" + mParentId - + ", mConversationId=" + mConversationId; + + ", mConversationId=" + mConversationId + + ", mDemoted=" + mDemoted; } /** @hide */ diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index c191a0daeb38..eb4af1c2a979 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -61,7 +61,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "false"); DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false"); DEFAULT_FLAGS.put("settings_conditionals", "false"); - DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false"); + DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true"); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt index 820c042e42ff..f7fe064724a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection +import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_HIGH import android.app.NotificationManager.IMPORTANCE_MIN import android.service.notification.NotificationListenerService.Ranking @@ -191,9 +192,9 @@ open class NotificationRankingManager @Inject constructor( } private fun NotificationEntry.isPeopleNotification() = - sbn.isPeopleNotification() - private fun StatusBarNotification.isPeopleNotification() = - peopleNotificationIdentifier.isPeopleNotification(this) + sbn.isPeopleNotification(channel) + private fun StatusBarNotification.isPeopleNotification(channel: NotificationChannel) = + peopleNotificationIdentifier.isPeopleNotification(this, channel) private fun NotificationEntry.isHighPriority() = highPriorityProvider.isHighPriority(this) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 3cc5e62c0bda..ccd7fa3c6837 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -99,7 +99,8 @@ public class HighPriorityProvider { } private boolean isPeopleNotification(NotificationEntry entry) { - return mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn()); + return mPeopleNotificationIdentifier.isPeopleNotification( + entry.getSbn(), entry.getChannel()); } private boolean hasUserSetImportance(NotificationEntry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt index 452d1eb95aab..5c90211ca6ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt @@ -18,13 +18,14 @@ package com.android.systemui.statusbar.notification.people import android.app.Notification import android.content.Context +import android.app.NotificationChannel import android.service.notification.StatusBarNotification import android.util.FeatureFlagUtils import javax.inject.Inject import javax.inject.Singleton interface PeopleNotificationIdentifier { - fun isPeopleNotification(sbn: StatusBarNotification): Boolean + fun isPeopleNotification(sbn: StatusBarNotification, channel: NotificationChannel): Boolean } @Singleton @@ -33,12 +34,13 @@ class PeopleNotificationIdentifierImpl @Inject constructor( private val context: Context ) : PeopleNotificationIdentifier { - override fun isPeopleNotification(sbn: StatusBarNotification) = - (sbn.notification.notificationStyle == Notification.MessagingStyle::class.java && + override fun isPeopleNotification(sbn: StatusBarNotification, channel: NotificationChannel) = + ((sbn.notification.notificationStyle == Notification.MessagingStyle::class.java && (sbn.notification.shortcutId != null || FeatureFlagUtils.isEnabled( context, FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ ))) || - personExtractor.isPersonNotification(sbn) + personExtractor.isPersonNotification(sbn)) && + !channel.isDemoted }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index ec420f312b06..3b106cbe10d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -25,6 +25,7 @@ import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_BUBBLE; +import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_DEMOTE; import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_FAVORITE; import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_HOME; import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_MUTE; @@ -61,6 +62,7 @@ import android.util.Slog; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.widget.Button; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -151,6 +153,11 @@ public class NotificationConversationInfo extends LinearLayout implements closeControls(v, true); }; + private OnClickListener mOnDemoteClick = v -> { + mSelectedAction = ACTION_DEMOTE; + closeControls(v, true); + }; + public NotificationConversationInfo(Context context, AttributeSet attrs) { super(context, attrs); } @@ -295,6 +302,8 @@ public class NotificationConversationInfo extends LinearLayout implements mContext.getDrawable(R.drawable.ic_notifications_alert), null, null, null); } + ImageButton demote = findViewById(R.id.demote); + demote.setOnClickListener(mOnDemoteClick); } private void bindHeader() { @@ -609,7 +618,7 @@ public class NotificationConversationInfo extends LinearLayout implements } break; case ACTION_DEMOTE: - // TODO: when demotion status field exists on notificationchannel + mChannelToUpdate.setDemoted(!mChannelToUpdate.isDemoted()); break; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index cc5514f1ff68..d852fa151fd3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -571,7 +571,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { } private NotificationEntry createNotification() { - Notification.Builder n = new Notification.Builder(mContext, "") + Notification.Builder n = new Notification.Builder(mContext, "id") .setSmallIcon(R.drawable.ic_person) .setContentTitle("Title") .setContentText("Text"); @@ -582,6 +582,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { .setUid(TEST_UID) .setId(mId++) .setNotification(n.build()) + .setChannel(new NotificationChannel("id", "", IMPORTANCE_DEFAULT)) .setUser(new UserHandle(ActivityManager.getCurrentUser())) .build(); } @@ -616,7 +617,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { @Test public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications() { Assert.sMainLooper = TestableLooper.get(this).getLooper(); - Notification.Builder n = new Notification.Builder(mContext, "") + Notification.Builder n = new Notification.Builder(mContext, "di") .setSmallIcon(R.drawable.ic_person) .setContentTitle("Title") .setContentText("Text"); @@ -628,6 +629,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { .setId(mId++) .setNotification(n.build()) .setUser(new UserHandle(ActivityManager.getCurrentUser())) + .setChannel(new NotificationChannel("id", "", IMPORTANCE_DEFAULT)) .build(); mEntryManager.addActiveNotificationForTest(mEntry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java index 93909dc4d330..7c3665bfe6fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java @@ -60,7 +60,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { final NotificationEntry entry = new NotificationEntryBuilder() .setImportance(IMPORTANCE_HIGH) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(false); // THEN it has high priority assertTrue(mHighPriorityProvider.isHighPriority(entry)); @@ -75,7 +76,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setNotification(notification) .setImportance(IMPORTANCE_LOW) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(true); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(true); // THEN it has high priority assertTrue(mHighPriorityProvider.isHighPriority(entry)); @@ -90,7 +92,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { final NotificationEntry entry = new NotificationEntryBuilder() .setNotification(notification) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(false); // THEN it has high priority assertTrue(mHighPriorityProvider.isHighPriority(entry)); @@ -106,7 +109,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setNotification(notification) .setImportance(IMPORTANCE_LOW) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(false); // THEN it has high priority assertTrue(mHighPriorityProvider.isHighPriority(entry)); @@ -122,7 +126,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setNotification(notification) .setImportance(IMPORTANCE_MIN) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(false); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(false); // THEN it does NOT have high priority assertFalse(mHighPriorityProvider.isHighPriority(entry)); @@ -144,7 +149,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setNotification(notification) .setChannel(channel) .build(); - when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn())).thenReturn(true); + when(mPeopleNotificationIdentifier.isPeopleNotification(entry.getSbn(), entry.getChannel())) + .thenReturn(true); // THEN it does NOT have high priority assertFalse(mHighPriorityProvider.isHighPriority(entry)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt index e27319103525..7ab4846ea066 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection import android.app.Notification +import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_HIGH import android.app.NotificationManager.IMPORTANCE_LOW @@ -81,6 +82,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setNotification( Notification.Builder(mContext, "test") .build()) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setUser(mContext.getUser()) .setOverrideGroupKey("") .build() @@ -94,6 +96,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setNotification( Notification.Builder(mContext, "test") .build()) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setUser(mContext.getUser()) .setOverrideGroupKey("") .build() @@ -116,6 +119,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setOpPkg("pkg") .setTag("tag") .setNotification(aN) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setUser(mContext.getUser()) .setOverrideGroupKey("") .build() @@ -130,6 +134,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setOpPkg("pkg2") .setTag("tag") .setNotification(bN) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setUser(mContext.getUser()) .setOverrideGroupKey("") .build() @@ -149,6 +154,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setTag("tag") .setNotification(notif) .setUser(mContext.user) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setOverrideGroupKey("") .build() @@ -168,6 +174,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setTag("tag") .setNotification(notif) .setUser(mContext.user) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) .setOverrideGroupKey("") .build() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 0bf458cac618..61f0b265e874 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -62,6 +62,7 @@ import android.util.Slog; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -684,6 +685,34 @@ public class NotificationConversationInfoTest extends SysuiTestCase { } @Test + public void testDemote() throws Exception { + mNotificationInfo.bindNotification( + mShortcutManager, + mLauncherApps, + mMockPackageManager, + mMockINotificationManager, + mVisualStabilityManager, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + null, + null, + null, + true); + + + ImageButton demote = mNotificationInfo.findViewById(R.id.demote); + demote.performClick(); + mTestableLooper.processAllMessages(); + + ArgumentCaptor<NotificationChannel> captor = + ArgumentCaptor.forClass(NotificationChannel.class); + verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( + anyString(), anyInt(), captor.capture()); + assertTrue(captor.getValue().isDemoted()); + } + + @Test public void testMute_mute() throws Exception { mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); mConversationChannel.setImportance(IMPORTANCE_DEFAULT); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 7ac45f027327..6f1657441fb5 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -227,6 +227,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertEquals(expected.getLightColor(), actual.getLightColor()); assertEquals(expected.getParentChannelId(), actual.getParentChannelId()); assertEquals(expected.getConversationId(), actual.getConversationId()); + assertEquals(expected.isDemoted(), actual.isDemoted()); } private void compareChannelsParentChild(NotificationChannel parent, @@ -355,6 +356,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); channel2.setLightColor(Color.BLUE); channel2.setConversationId("id1", "conversation"); + channel2.setDemoted(true); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); |