Add filtering to notification channel settings

Allow apps that are launching this page to specify targeted subsets of
settings that should be shown.

Test: settings notification robotests
Bug: 177246841
Change-Id: Ib491c43f1861a9775e3b25f39134cdbe105a7ff8
This commit is contained in:
Julia Reynolds
2021-02-11 21:29:41 -05:00
parent d7af6821dc
commit 4dc7795eb3
66 changed files with 1067 additions and 333 deletions

View File

@@ -32,7 +32,6 @@ import android.view.View;
import android.widget.ImageView;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
@@ -67,8 +66,10 @@ public class AppBubbleListPreferenceController extends AppConversationListPrefer
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group,
Drawable conversationDrawable,
ShortcutInfo conversationInfo,
RestrictedLockUtils.EnforcedAdmin admin) {
super.onResume(appRow, channel, group, conversationDrawable, conversationInfo, admin);
RestrictedLockUtils.EnforcedAdmin admin,
List<String> preferenceFilter) {
super.onResume(appRow, channel, group, conversationDrawable, conversationInfo, admin,
preferenceFilter);
// In case something changed in the foreground (e.g. via bubble button on notification)
loadConversationsAndPopulate();
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.content.Context;
import android.util.Slog;
@@ -47,6 +48,11 @@ public class AddToHomeScreenPreferenceController extends NotificationPreferenceC
return mConversationInfo != null;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_LAUNCHER);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY.equals(preference.getKey())) {

View File

@@ -58,6 +58,11 @@ public class AllowSoundPreferenceController extends NotificationPreferenceContro
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_SOUND);
}
@Override
public void updateState(Preference preference) {
if (mChannel != null) {

View File

@@ -90,7 +90,7 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen
}
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, null, null, null, null, mSuspendedAppsAdmin);
controller.onResume(mAppRow, null, null, null, null, mSuspendedAppsAdmin, null);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();

View File

@@ -114,6 +114,11 @@ public class AppChannelsBypassingDndPreferenceController extends NotificationPre
return mAppRow != null;
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public void updateState(Preference preference) {
if (mAppRow != null) {

View File

@@ -53,7 +53,7 @@ public class AppChannelsBypassingDndSettings extends NotificationSettings {
}
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, null, null, null, null, mSuspendedAppsAdmin);
controller.onResume(mAppRow, null, null, null, null, mSuspendedAppsAdmin, null);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();

View File

@@ -74,6 +74,11 @@ public class AppConversationListPreferenceController extends NotificationPrefere
mAppRow.pkg, mAppRow.uid);
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public void updateState(Preference preference) {
mPreference = (PreferenceCategory) preference;

View File

@@ -48,6 +48,11 @@ public class AppLinkPreferenceController extends NotificationPreferenceControlle
return mAppRow.settingsIntent != null;
}
@Override
boolean isIncludedInFilter() {
return false;
}
public void updateState(Preference preference) {
if (mAppRow != null) {
preference.setIntent(mAppRow.settingsIntent);

View File

@@ -79,7 +79,8 @@ public class AppNotificationSettings extends NotificationSettings {
}
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, null, null, mSuspendedAppsAdmin);
controller.onResume(mAppRow, mChannel, mChannelGroup, null, null, mSuspendedAppsAdmin,
null);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();

View File

@@ -18,6 +18,7 @@ package com.android.settings.notification.app;
import static android.provider.Settings.Secure.NOTIFICATION_BADGING;
import android.app.NotificationChannel;
import android.content.Context;
import android.provider.Settings;
@@ -67,6 +68,11 @@ public class BadgePreferenceController extends NotificationPreferenceController
return true;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_LAUNCHER);
}
public void updateState(Preference preference) {
if (mAppRow != null) {
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;

View File

@@ -20,6 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.widget.Switch;
@@ -55,9 +56,17 @@ public class BlockPreferenceController extends NotificationPreferenceController
if (mAppRow == null) {
return false;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
return false;
}
return true;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE);
}
public void updateState(Preference preference) {
SettingsMainSwitchPreference bar = (SettingsMainSwitchPreference) preference;
if (bar != null) {

View File

@@ -43,6 +43,11 @@ public class BubbleCategoryPreferenceController extends NotificationPreferenceCo
return areBubblesEnabled();
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public String getPreferenceKey() {
return KEY;

View File

@@ -43,6 +43,11 @@ public class BubbleLinkPreferenceController extends NotificationPreferenceContro
return areBubblesEnabled();
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public String getPreferenceKey() {
return KEY;

View File

@@ -21,6 +21,7 @@ import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
import android.app.ActivityManager;
import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.content.Context;
import android.provider.Settings;
@@ -84,6 +85,11 @@ public class BubblePreferenceController extends NotificationPreferenceController
return true;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
@Override
public void updateState(Preference preference) {
if (mIsAppPage && mAppRow != null) {

View File

@@ -66,6 +66,11 @@ public class BubbleSummaryPreferenceController extends NotificationPreferenceCon
return isGloballyEnabled() && mBackend.hasSentValidMsg(mAppRow.pkg, mAppRow.uid);
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public String getPreferenceKey() {
return KEY;

View File

@@ -84,6 +84,11 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr
return true;
}
@Override
boolean isIncludedInFilter() {
return false;
}
@Override
public void updateState(Preference preference) {
mPreference = (PreferenceCategory) preference;

View File

@@ -79,7 +79,8 @@ public class ChannelNotificationSettings extends NotificationSettings {
}
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, null, null, mSuspendedAppsAdmin);
controller.onResume(mAppRow, mChannel, mChannelGroup, null, null, mSuspendedAppsAdmin,
mPreferenceFilter);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.content.Context;
import android.text.TextUtils;
@@ -56,6 +57,11 @@ public class ConversationDemotePreferenceController extends NotificationPreferen
return !TextUtils.isEmpty(mChannel.getConversationId()) && !mChannel.isDemoted();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
public void updateState(Preference preference) {
preference.setEnabled(mAdmin == null);
}

View File

@@ -59,6 +59,11 @@ public class ConversationHeaderPreferenceController extends NotificationPreferen
return mAppRow != null;
}
@Override
boolean isIncludedInFilter() {
return true;
}
@Override
public void updateState(Preference preference) {
if (mAppRow != null && mFragment != null) {

View File

@@ -49,7 +49,7 @@ public class ConversationNotificationSettings extends NotificationSettings {
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, mConversationDrawable,
mConversationInfo, mSuspendedAppsAdmin);
mConversationInfo, mSuspendedAppsAdmin, null);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.content.Context;
import android.util.Pair;
@@ -53,6 +54,12 @@ public class ConversationPriorityPreferenceController extends NotificationPrefer
return true;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE)
|| mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
public void updateState(Preference preference) {
if (mAppRow != null) {
preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.content.Context;
import android.text.TextUtils;
@@ -56,6 +57,11 @@ public class ConversationPromotePreferenceController extends NotificationPrefere
return !TextUtils.isEmpty(mChannel.getConversationId()) && mChannel.isDemoted();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
public void updateState(Preference preference) {
preference.setEnabled(mAdmin == null);
}

View File

@@ -51,6 +51,11 @@ public class DeletedChannelsPreferenceController extends NotificationPreferenceC
return mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0;
}
@Override
boolean isIncludedInFilter() {
return false;
}
public void updateState(Preference preference) {
if (mAppRow != null) {
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);

View File

@@ -54,6 +54,11 @@ public class DescriptionPreferenceController extends NotificationPreferenceContr
return false;
}
@Override
boolean isIncludedInFilter() {
return false;
}
public void updateState(Preference preference) {
if (mAppRow != null) {
if (mChannel != null) {

View File

@@ -47,6 +47,11 @@ public class DndPreferenceController extends NotificationPreferenceController
return true;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_ZEN);
}
public void updateState(Preference preference) {
if (mChannel != null) {
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;

View File

@@ -59,6 +59,11 @@ public class HeaderPreferenceController extends NotificationPreferenceController
return mAppRow != null;
}
@Override
boolean isIncludedInFilter() {
return true;
}
@Override
public void updateState(Preference preference) {
if (mAppRow != null && mFragment != null) {

View File

@@ -22,12 +22,12 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import android.app.NotificationChannel;
import android.content.Context;
import androidx.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedSwitchPreference;
import androidx.preference.Preference;
public class HighImportancePreferenceController extends NotificationPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
@@ -60,6 +60,11 @@ public class HighImportancePreferenceController extends NotificationPreferenceCo
return mChannel.getImportance() >= IMPORTANCE_DEFAULT;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE);
}
@Override
public void updateState(Preference preference) {
if (mAppRow != null && mChannel != null) {

View File

@@ -58,6 +58,11 @@ public class ImportancePreferenceController extends NotificationPreferenceContro
return !isDefaultChannel();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE);
}
@Override
public void updateState(Preference preference) {
if (mAppRow!= null && mChannel != null) {

View File

@@ -47,9 +47,17 @@ public class InvalidConversationInfoPreferenceController extends NotificationPre
if (mAppRow.banned) {
return false;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
return false;
}
return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
@Override
public void updateState(Preference preference) {
if (mAppRow == null) {

View File

@@ -47,9 +47,17 @@ public class InvalidConversationPreferenceController extends NotificationPrefere
if (mAppRow.banned) {
return false;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
return false;
}
return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_CONVERSATION);
}
@Override
public void updateState(Preference preference) {
if (mAppRow == null) {

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
@@ -53,6 +54,11 @@ public class LightsPreferenceController extends NotificationPreferenceController
&& !isDefaultChannel();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_LOCKED_DEVICE);
}
public void updateState(Preference preference) {
if (mChannel != null) {
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;

View File

@@ -60,6 +60,11 @@ public class MinImportancePreferenceController extends NotificationPreferenceCon
return mChannel.getImportance() <= IMPORTANCE_LOW;
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE);
}
@Override
public void updateState(Preference preference) {
if (mAppRow != null && mChannel != null) {

View File

@@ -36,6 +36,7 @@ import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
/**
@@ -60,6 +61,7 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
protected Drawable mConversationDrawable;
@Nullable
protected ShortcutInfo mConversationInfo;
protected List<String> mPreferenceFilter;
public NotificationPreferenceController(Context context, NotificationBackend backend) {
super(context);
@@ -87,6 +89,9 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
}
}
if (mChannel != null) {
if (mPreferenceFilter != null && !isIncludedInFilter()) {
return false;
}
return mChannel.getImportance() != IMPORTANCE_NONE;
}
return true;
@@ -96,15 +101,19 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group,
Drawable conversationDrawable,
ShortcutInfo conversationInfo,
RestrictedLockUtils.EnforcedAdmin admin) {
RestrictedLockUtils.EnforcedAdmin admin,
List<String> preferenceFilter) {
mAppRow = appRow;
mChannel = channel;
mChannelGroup = group;
mAdmin = admin;
mConversationDrawable = conversationDrawable;
mConversationInfo = conversationInfo;
mPreferenceFilter = preferenceFilter;
}
abstract boolean isIncludedInFilter();
protected boolean checkCanBeVisible(int minImportanceVisible) {
if (mChannel == null) {
Log.w(TAG, "No channel");

View File

@@ -74,6 +74,7 @@ abstract public class NotificationSettings extends DashboardFragment {
protected NotificationBackend.AppRow mAppRow;
protected Drawable mConversationDrawable;
protected ShortcutInfo mConversationInfo;
protected List<String> mPreferenceFilter;
protected boolean mShowLegacyChannelConfig = false;
protected boolean mListeningToPackageRemove;
@@ -119,6 +120,7 @@ abstract public class NotificationSettings extends DashboardFragment {
loadChannel();
loadAppRow();
loadChannelGroup();
loadPreferencesFilter();
collectConfigActivities();
if (use(HeaderPreferenceController.class) != null) {
@@ -131,7 +133,7 @@ abstract public class NotificationSettings extends DashboardFragment {
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, null, null,
mSuspendedAppsAdmin);
mSuspendedAppsAdmin, mPreferenceFilter);
}
}
}
@@ -181,9 +183,17 @@ abstract public class NotificationSettings extends DashboardFragment {
loadChannel();
loadConversation();
loadChannelGroup();
loadPreferencesFilter();
collectConfigActivities();
}
private void loadPreferencesFilter() {
Intent intent = getActivity().getIntent();
mPreferenceFilter = intent != null
? intent.getStringArrayListExtra(Settings.EXTRA_CHANNEL_FILTER_LIST)
: null;
}
private void loadChannel() {
Intent intent = getActivity().getIntent();
String channelId = intent != null ? intent.getStringExtra(Settings.EXTRA_CHANNEL_ID) : null;

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.content.Context;
import androidx.preference.Preference;
@@ -42,11 +43,19 @@ public class NotificationsOffPreferenceController extends NotificationPreference
if (mAppRow == null) {
return false;
}
if (mPreferenceFilter != null && !isIncludedInFilter()) {
return false;
}
// Available only when other controllers are unavailable - this UI replaces the UI that
// would give more detailed notification controls.
return !super.isAvailable();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_IMPORTANCE);
}
public void updateState(Preference preference) {
if (mAppRow != null) {
if (mChannel != null) {

View File

@@ -68,6 +68,11 @@ public class SoundPreferenceController extends NotificationPreferenceController
return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_SOUND);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Vibrator;
@@ -54,6 +55,11 @@ public class VibrationPreferenceController extends NotificationPreferenceControl
&& mVibrator.hasVibrator();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_VIBRATION);
}
public void updateState(Preference preference) {
if (mChannel != null) {
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;

View File

@@ -68,6 +68,11 @@ public class VisibilityPreferenceController extends NotificationPreferenceContro
return checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure();
}
@Override
boolean isIncludedInFilter() {
return mPreferenceFilter.contains(NotificationChannel.EDIT_LOCKED_DEVICE);
}
public void updateState(Preference preference) {
if (mChannel != null && mAppRow != null) {
RestrictedListPreference pref = (RestrictedListPreference) preference;