Loading aconfig/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ aconfig_declarations { "settings_connecteddevice_flag_declarations.aconfig", "settings_globalintl_flag_declarations.aconfig", "settings_experience_flag_declarations.aconfig", "settings_notification_flag_declarations.aconfig", "settings_onboarding_experience_flag_declarations.aconfig", "settings_telephony_flag_declarations.aconfig", "settings_biometrics_integration_declarations.aconfig", Loading aconfig/settings_notification_flag_declarations.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line package: "com.android.settings.flags" flag { name: "dedupe_dnd_settings_channels" namespace: "systemui" description: "Controls adding group names to channel names in the DND>Apps settings page" bug: "294333850" } src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java +29 −0 Original line number Diff line number Diff line Loading @@ -39,13 +39,18 @@ import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SubSettingLauncher; import com.android.settings.flags.Flags; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.RestrictedSwitchPreference; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Populates the PreferenceCategory with notification channels associated with the given app. Loading @@ -61,6 +66,9 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre private RestrictedSwitchPreference mAllNotificationsToggle; private PreferenceCategory mPreferenceCategory; private List<NotificationChannel> mChannels = new ArrayList<>(); private Set<String> mDuplicateChannelNames = new HashSet<>(); private Map<NotificationChannel, String> mChannelGroupNames = new HashMap<NotificationChannel, String>(); public AppChannelsBypassingDndPreferenceController( Context context, Loading Loading @@ -135,10 +143,20 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre List<NotificationChannel> newChannelList = new ArrayList<>(); List<NotificationChannelGroup> mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList(); Set<String> allChannelNames = new HashSet<>(); for (NotificationChannelGroup channelGroup : mChannelGroupList) { for (NotificationChannel channel : channelGroup.getChannels()) { if (!isConversation(channel)) { newChannelList.add(channel); if (Flags.dedupeDndSettingsChannels()) { mChannelGroupNames.put(channel, channelGroup.getName().toString()); // Check if channel name is unique on this page; if not, save it. if (allChannelNames.contains(channel.getName())) { mDuplicateChannelNames.add(channel.getName().toString()); } else { allChannelNames.add(channel.getName().toString()); } } } } } Loading Loading @@ -172,6 +190,17 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre && isChannelConfigurable(channel) && showNotification(channel)); channelPreference.setTitle(BidiFormatter.getInstance().unicodeWrap(channel.getName())); if (Flags.dedupeDndSettingsChannels()) { // If the channel shares its name with another channel, set group name as summary // to disambiguate in the list. if (mDuplicateChannelNames.contains(channel.getName().toString()) && mChannelGroupNames.containsKey(channel) && mChannelGroupNames.get(channel) != null && !mChannelGroupNames.get(channel).isEmpty()) { channelPreference.setSummary(BidiFormatter.getInstance().unicodeWrap( mChannelGroupNames.get(channel))); } } channelPreference.setChecked(showNotificationInDnd(channel)); channelPreference.setOnPreferenceChangeListener( new Preference.OnPreferenceChangeListener() { Loading tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -26,16 +26,19 @@ import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.Context; import android.content.pm.ParceledListSlice; import android.platform.test.flag.junit.SetFlagsRule; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.flags.Flags; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.PrimarySwitchPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -51,6 +54,9 @@ import java.util.Collections; @LooperMode(LooperMode.Mode.LEGACY) public class AppChannelsBypassingDndPreferenceControllerTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private NotificationBackend mBackend; Loading Loading @@ -150,4 +156,44 @@ public class AppChannelsBypassingDndPreferenceControllerTest { } return new ParceledListSlice<>(Collections.singletonList(group)); } @Test public void displayPreference_duplicateChannelName_AddsGroupNameAsSummary() { mSetFlagsRule.enableFlags(Flags.FLAG_DEDUPE_DND_SETTINGS_CHANNELS); NotificationChannelGroup group1 = new NotificationChannelGroup("group1_id", "Group1"); NotificationChannelGroup group2 = new NotificationChannelGroup("group2_id", "Group2"); group1.addChannel(new NotificationChannel("mail_group1_id", "Mail", NotificationManager.IMPORTANCE_DEFAULT)); group1.addChannel(new NotificationChannel("other_group1_id", "Other", NotificationManager.IMPORTANCE_DEFAULT)); group2.addChannel(new NotificationChannel("music_group2_id", "Music", NotificationManager.IMPORTANCE_DEFAULT)); // This channel has the same name as a channel in group1. group2.addChannel(new NotificationChannel("mail_group2_id", "Mail", NotificationManager.IMPORTANCE_DEFAULT)); ParceledListSlice<NotificationChannelGroup> groups = new ParceledListSlice<>( new ArrayList<NotificationChannelGroup>() { { add(group1); add(group2); } } ); when(mBackend.getGroups(eq(mAppRow.pkg), eq(mAppRow.uid))).thenReturn(groups); mController.displayPreference(mPreferenceScreen); ShadowApplication.runBackgroundTasks(); // Check that we've added the group name as a summary to channels that have identical names. // Channels are also alphabetized. assertThat(mCategory.getPreference(1).getTitle().toString()).isEqualTo("Mail"); assertThat(mCategory.getPreference(1).getSummary().toString()).isEqualTo("Group1"); assertThat(mCategory.getPreference(2).getTitle().toString()).isEqualTo("Mail"); assertThat(mCategory.getPreference(2).getSummary().toString()).isEqualTo("Group2"); assertThat(mCategory.getPreference(3).getTitle().toString()).isEqualTo("Music"); assertThat(mCategory.getPreference(4).getTitle().toString()).isEqualTo("Other"); } } Loading
aconfig/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ aconfig_declarations { "settings_connecteddevice_flag_declarations.aconfig", "settings_globalintl_flag_declarations.aconfig", "settings_experience_flag_declarations.aconfig", "settings_notification_flag_declarations.aconfig", "settings_onboarding_experience_flag_declarations.aconfig", "settings_telephony_flag_declarations.aconfig", "settings_biometrics_integration_declarations.aconfig", Loading
aconfig/settings_notification_flag_declarations.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line package: "com.android.settings.flags" flag { name: "dedupe_dnd_settings_channels" namespace: "systemui" description: "Controls adding group names to channel names in the DND>Apps settings page" bug: "294333850" }
src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java +29 −0 Original line number Diff line number Diff line Loading @@ -39,13 +39,18 @@ import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SubSettingLauncher; import com.android.settings.flags.Flags; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.RestrictedSwitchPreference; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Populates the PreferenceCategory with notification channels associated with the given app. Loading @@ -61,6 +66,9 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre private RestrictedSwitchPreference mAllNotificationsToggle; private PreferenceCategory mPreferenceCategory; private List<NotificationChannel> mChannels = new ArrayList<>(); private Set<String> mDuplicateChannelNames = new HashSet<>(); private Map<NotificationChannel, String> mChannelGroupNames = new HashMap<NotificationChannel, String>(); public AppChannelsBypassingDndPreferenceController( Context context, Loading Loading @@ -135,10 +143,20 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre List<NotificationChannel> newChannelList = new ArrayList<>(); List<NotificationChannelGroup> mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList(); Set<String> allChannelNames = new HashSet<>(); for (NotificationChannelGroup channelGroup : mChannelGroupList) { for (NotificationChannel channel : channelGroup.getChannels()) { if (!isConversation(channel)) { newChannelList.add(channel); if (Flags.dedupeDndSettingsChannels()) { mChannelGroupNames.put(channel, channelGroup.getName().toString()); // Check if channel name is unique on this page; if not, save it. if (allChannelNames.contains(channel.getName())) { mDuplicateChannelNames.add(channel.getName().toString()); } else { allChannelNames.add(channel.getName().toString()); } } } } } Loading Loading @@ -172,6 +190,17 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre && isChannelConfigurable(channel) && showNotification(channel)); channelPreference.setTitle(BidiFormatter.getInstance().unicodeWrap(channel.getName())); if (Flags.dedupeDndSettingsChannels()) { // If the channel shares its name with another channel, set group name as summary // to disambiguate in the list. if (mDuplicateChannelNames.contains(channel.getName().toString()) && mChannelGroupNames.containsKey(channel) && mChannelGroupNames.get(channel) != null && !mChannelGroupNames.get(channel).isEmpty()) { channelPreference.setSummary(BidiFormatter.getInstance().unicodeWrap( mChannelGroupNames.get(channel))); } } channelPreference.setChecked(showNotificationInDnd(channel)); channelPreference.setOnPreferenceChangeListener( new Preference.OnPreferenceChangeListener() { Loading
tests/robotests/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceControllerTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -26,16 +26,19 @@ import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.Context; import android.content.pm.ParceledListSlice; import android.platform.test.flag.junit.SetFlagsRule; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.flags.Flags; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.PrimarySwitchPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -51,6 +54,9 @@ import java.util.Collections; @LooperMode(LooperMode.Mode.LEGACY) public class AppChannelsBypassingDndPreferenceControllerTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private NotificationBackend mBackend; Loading Loading @@ -150,4 +156,44 @@ public class AppChannelsBypassingDndPreferenceControllerTest { } return new ParceledListSlice<>(Collections.singletonList(group)); } @Test public void displayPreference_duplicateChannelName_AddsGroupNameAsSummary() { mSetFlagsRule.enableFlags(Flags.FLAG_DEDUPE_DND_SETTINGS_CHANNELS); NotificationChannelGroup group1 = new NotificationChannelGroup("group1_id", "Group1"); NotificationChannelGroup group2 = new NotificationChannelGroup("group2_id", "Group2"); group1.addChannel(new NotificationChannel("mail_group1_id", "Mail", NotificationManager.IMPORTANCE_DEFAULT)); group1.addChannel(new NotificationChannel("other_group1_id", "Other", NotificationManager.IMPORTANCE_DEFAULT)); group2.addChannel(new NotificationChannel("music_group2_id", "Music", NotificationManager.IMPORTANCE_DEFAULT)); // This channel has the same name as a channel in group1. group2.addChannel(new NotificationChannel("mail_group2_id", "Mail", NotificationManager.IMPORTANCE_DEFAULT)); ParceledListSlice<NotificationChannelGroup> groups = new ParceledListSlice<>( new ArrayList<NotificationChannelGroup>() { { add(group1); add(group2); } } ); when(mBackend.getGroups(eq(mAppRow.pkg), eq(mAppRow.uid))).thenReturn(groups); mController.displayPreference(mPreferenceScreen); ShadowApplication.runBackgroundTasks(); // Check that we've added the group name as a summary to channels that have identical names. // Channels are also alphabetized. assertThat(mCategory.getPreference(1).getTitle().toString()).isEqualTo("Mail"); assertThat(mCategory.getPreference(1).getSummary().toString()).isEqualTo("Group1"); assertThat(mCategory.getPreference(2).getTitle().toString()).isEqualTo("Mail"); assertThat(mCategory.getPreference(2).getSummary().toString()).isEqualTo("Group2"); assertThat(mCategory.getPreference(3).getTitle().toString()).isEqualTo("Music"); assertThat(mCategory.getPreference(4).getTitle().toString()).isEqualTo("Other"); } }