Move channel listing into a pref controller

And a hidden preference category. This makes
hiding/showing the list a lot cleaner and also allows more
of the code to be tested.

Also delete some unused code that no longer complied after
this refactor.

Fixes: 133443871
Test: atest
Change-Id: I4a5fe0e075019bae2df44a0a9dcec26a40ee6d12
(cherry picked from commit a295d71c94fbf9411f6ee6062de39aa34a574375)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ff3f650..13bea74 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2594,13 +2594,6 @@
                 android:value="com.android.settings.notification.AppNotificationSettings" />
         </activity>
 
-        <!-- Show channel group-level notification settings (group passed in as extras) -->
-        <activity android:name="Settings$ChannelGroupNotificationSettingsActivity"
-                  android:exported="true">
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                       android:value="com.android.settings.notification.ChannelGroupNotificationSettings" />
-        </activity>
-
         <!-- Show channel-level notification settings (channel passed in as extras) -->
         <activity android:name="Settings$ChannelNotificationSettingsActivity"
                   android:label="@string/notification_channel_title"
diff --git a/res/layout/empty_view.xml b/res/layout/empty_view.xml
new file mode 100644
index 0000000..33218f7
--- /dev/null
+++ b/res/layout/empty_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:visibility="gone"/>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index fedd3cc..7330f8d 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -30,6 +30,11 @@
         android:key="block_desc" />
 
     <!-- Channels/Channel groups added here -->
+    <PreferenceCategory
+        android:key="channels"
+        android:layout="@layout/empty_view"
+        settings:allowDividerAbove="false"
+        settings:allowDividerBelow="false" />
 
     <!-- Importance toggle -->
     <com.android.settingslib.RestrictedSwitchPreference
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 5a81e71..384f262 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -106,7 +106,6 @@
 import com.android.settings.nfc.PaymentSettings;
 import com.android.settings.notification.AppBubbleNotificationSettings;
 import com.android.settings.notification.AppNotificationSettings;
-import com.android.settings.notification.ChannelGroupNotificationSettings;
 import com.android.settings.notification.ChannelNotificationSettings;
 import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.NotificationAccessSettings;
@@ -238,7 +237,6 @@
             AppNotificationSettings.class.getName(),
             NotificationAssistantPicker.class.getName(),
             ChannelNotificationSettings.class.getName(),
-            ChannelGroupNotificationSettings.class.getName(),
             ApnSettings.class.getName(),
             ApnEditor.class.getName(),
             WifiCallingSettings.class.getName(),
diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
index ccccd39..ff76779 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
@@ -20,7 +20,7 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
-import static com.android.settings.notification.NotificationSettingsBase.ARG_FROM_SETTINGS;
+import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
 
 import android.app.Application;
 import android.app.NotificationChannel;
@@ -110,7 +110,7 @@
      *
      * Note:
      * When the sent count of notification channels is the same, follow the sorting mechanism from
-     * {@link com.android.settings.notification.NotificationSettingsBase#mChannelComparator}.
+     * {@link com.android.settings.notification.ChannelListPreferenceController}.
      * Since slice view only shows displayable notification channels, so those deleted ones are
      * excluded from the comparison here.
      */
@@ -257,7 +257,6 @@
         channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
         channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPackageName);
         channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
-        channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
 
         final Intent channelIntent = new SubSettingLauncher(mContext)
                 .setDestination(ChannelNotificationSettings.class.getName())
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 531d8fa..dc06f47 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,46 +16,34 @@
 
 package com.android.settings.notification;
 
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.Log;
 
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
-import com.android.settings.widget.MasterSwitchPreference;
-import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
 /** These settings are per app, so should not be returned in global search results. */
 public class AppNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "AppNotificationSettings";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static String KEY_GENERAL_CATEGORY = "categories";
     private static String KEY_ADVANCED_CATEGORY = "app_advanced";
     private static String KEY_BADGE = "badge";
     private static String KEY_APP_LINK = "app_link";
     private static String KEY_BUBBLE = "bubble_link_pref";
     private static String[] LEGACY_NON_ADVANCED_KEYS = {KEY_BADGE, KEY_APP_LINK, KEY_BUBBLE};
 
-    private List<NotificationChannelGroup> mChannelGroupList;
-
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.NOTIFICATION_APP_NOTIFICATION;
@@ -91,26 +79,6 @@
             return;
         }
 
-        if (!mShowLegacyChannelConfig) {
-            // Load channel settings
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... unused) {
-                    mChannelGroupList = mBackend.getGroups(mPkg, mUid).getList();
-                    Collections.sort(mChannelGroupList, mChannelGroupComparator);
-                    return null;
-                }
-
-                @Override
-                protected void onPostExecute(Void unused) {
-                    if (getHost() == null) {
-                        return;
-                    }
-                    populateList();
-                }
-            }.execute();
-        }
-
         for (NotificationPreferenceController controller : mControllers) {
             controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
             controller.displayPreference(getPreferenceScreen());
@@ -154,125 +122,7 @@
         mControllers.add(new NotificationsOffPreferenceController(context));
         mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
         mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
+        mControllers.add(new ChannelListPreferenceController(context, mBackend));
         return new ArrayList<>(mControllers);
     }
-
-    private void populateList() {
-        if (!mDynamicPreferences.isEmpty()) {
-            for (Preference p : mDynamicPreferences) {
-                getPreferenceScreen().removePreference(p);
-            }
-            mDynamicPreferences.clear();
-        }
-        if (mChannelGroupList.isEmpty()) {
-            PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
-            groupCategory.setTitle(R.string.notification_channels);
-            groupCategory.setKey(KEY_GENERAL_CATEGORY);
-            getPreferenceScreen().addPreference(groupCategory);
-            mDynamicPreferences.add(groupCategory);
-
-            Preference empty = new Preference(getPrefContext());
-            empty.setTitle(R.string.no_channels);
-            empty.setEnabled(false);
-            groupCategory.addPreference(empty);
-        } else {
-            populateGroupList();
-            mImportanceListener.onImportanceChanged();
-        }
-    }
-
-    private void populateGroupList() {
-        for (NotificationChannelGroup group : mChannelGroupList) {
-            PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
-            groupCategory.setOrderingAsAdded(true);
-            getPreferenceScreen().addPreference(groupCategory);
-            mDynamicPreferences.add(groupCategory);
-            if (group.getId() == null) {
-                if (mChannelGroupList.size() > 1) {
-                    groupCategory.setTitle(R.string.notification_channels_other);
-                }
-                groupCategory.setKey(KEY_GENERAL_CATEGORY);
-            } else {
-                groupCategory.setTitle(group.getName());
-                groupCategory.setKey(group.getId());
-                populateGroupToggle(groupCategory, group);
-            }
-            if (!group.isBlocked()) {
-                final List<NotificationChannel> channels = group.getChannels();
-                Collections.sort(channels, mChannelComparator);
-                int N = channels.size();
-                for (int i = 0; i < N; i++) {
-                    final NotificationChannel channel = channels.get(i);
-                    populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
-                }
-            }
-        }
-    }
-
-    protected void populateGroupToggle(final PreferenceGroup parent,
-            NotificationChannelGroup group) {
-        RestrictedSwitchPreference preference = new RestrictedSwitchPreference(getPrefContext());
-        preference.setTitle(R.string.notification_switch_label);
-        preference.setEnabled(mSuspendedAppsAdmin == null
-                && isChannelGroupBlockable(group));
-        preference.setChecked(!group.isBlocked());
-        preference.setOnPreferenceClickListener(preference1 -> {
-            final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
-            group.setBlocked(!allowGroup);
-            mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
-
-            onGroupBlockStateChanged(group);
-            return true;
-        });
-
-        parent.addPreference(preference);
-    }
-
-    private Comparator<NotificationChannelGroup> mChannelGroupComparator =
-            new Comparator<NotificationChannelGroup>() {
-
-                @Override
-                public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
-                    // Non-grouped channels (in placeholder group with a null id) come last
-                    if (left.getId() == null && right.getId() != null) {
-                        return 1;
-                    } else if (right.getId() == null && left.getId() != null) {
-                        return -1;
-                    }
-                    return left.getId().compareTo(right.getId());
-                }
-            };
-
-    protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
-        if (group == null) {
-            return;
-        }
-        PreferenceGroup groupGroup = (
-                PreferenceGroup) getPreferenceScreen().findPreference(group.getId());
-
-        if (groupGroup != null) {
-            if (group.isBlocked()) {
-                List<Preference> toRemove = new ArrayList<>();
-                int childCount = groupGroup.getPreferenceCount();
-                for (int i = 0; i < childCount; i++) {
-                    Preference pref = groupGroup.getPreference(i);
-                    if (pref instanceof MasterSwitchPreference) {
-                        toRemove.add(pref);
-                    }
-                }
-                for (Preference pref : toRemove) {
-                    groupGroup.removePreference(pref);
-                }
-            } else {
-                final List<NotificationChannel> channels = group.getChannels();
-                Collections.sort(channels, mChannelComparator);
-                int N = channels.size();
-                for (int i = 0; i < N; i++) {
-                    final NotificationChannel channel = channels.get(i);
-                    populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
-                }
-            }
-        }
-    }
-
 }
diff --git a/src/com/android/settings/notification/ChannelGroupNotificationSettings.java b/src/com/android/settings/notification/ChannelGroupNotificationSettings.java
deleted file mode 100644
index 1f8b1c3..0000000
--- a/src/com/android/settings/notification/ChannelGroupNotificationSettings.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 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.settings.notification;
-
-import android.app.NotificationChannel;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class ChannelGroupNotificationSettings extends NotificationSettingsBase {
-    private static final String TAG = "ChannelGroupSettings";
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.NOTIFICATION_CHANNEL_GROUP;
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mAppRow == null || mChannelGroup == null) {
-            Log.w(TAG, "Missing package or uid or packageinfo or group");
-            finish();
-            return;
-        }
-
-        populateChannelList();
-        for (NotificationPreferenceController controller : mControllers) {
-            controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
-            controller.displayPreference(getPreferenceScreen());
-        }
-        updatePreferenceStates();
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.notification_group_settings;
-    }
-
-    @Override
-    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        mControllers = new ArrayList<>();
-        mControllers.add(new HeaderPreferenceController(context, this));
-        mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
-        mControllers.add(new AppLinkPreferenceController(context));
-        mControllers.add(new NotificationsOffPreferenceController(context));
-        mControllers.add(new DescriptionPreferenceController(context));
-        return new ArrayList<>(mControllers);
-    }
-
-    private void populateChannelList() {
-        if (!mDynamicPreferences.isEmpty()) {
-            // If there's anything in mDynamicPreferences, we've called populateChannelList twice.
-            // Clear out existing channels and log.
-            Log.w(TAG, "Notification channel group posted twice to settings - old size " +
-                    mDynamicPreferences.size() + ", new size " + mDynamicPreferences.size());
-            for (Preference p : mDynamicPreferences) {
-                getPreferenceScreen().removePreference(p);
-            }
-        }
-        if (mChannelGroup.getChannels().isEmpty()) {
-            Preference empty = new Preference(getPrefContext());
-            empty.setTitle(R.string.no_channels);
-            empty.setEnabled(false);
-            getPreferenceScreen().addPreference(empty);
-            mDynamicPreferences.add(empty);
-
-        } else {
-            final List<NotificationChannel> channels = mChannelGroup.getChannels();
-            Collections.sort(channels, mChannelComparator);
-            for (NotificationChannel channel : channels) {
-                mDynamicPreferences.add(populateSingleChannelPrefs(
-                        getPreferenceScreen(), channel, mChannelGroup.isBlocked()));
-            }
-
-        }
-    }
-}
diff --git a/src/com/android/settings/notification/ChannelListPreferenceController.java b/src/com/android/settings/notification/ChannelListPreferenceController.java
new file mode 100644
index 0000000..7ff407c
--- /dev/null
+++ b/src/com/android/settings/notification/ChannelListPreferenceController.java
@@ -0,0 +1,311 @@
+/*
+ * 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.settings.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.widget.MasterSwitchPreference;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.SwitchPreference;
+
+public class ChannelListPreferenceController extends NotificationPreferenceController {
+
+    private static final String KEY = "channels";
+    private static String KEY_GENERAL_CATEGORY = "categories";
+    public static final String ARG_FROM_SETTINGS = "fromSettings";
+
+    private List<NotificationChannelGroup> mChannelGroupList;
+    private PreferenceCategory mPreference;
+
+    public ChannelListPreferenceController(Context context, NotificationBackend backend) {
+        super(context, backend);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (mAppRow == null) {
+            return false;
+        }
+        if (mAppRow.banned) {
+            return false;
+        }
+        if (mChannel != null) {
+            if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
+                    || NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        mPreference = (PreferenceCategory) preference;
+        // Load channel settings
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList();
+                Collections.sort(mChannelGroupList, mChannelGroupComparator);
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void unused) {
+                if (mContext == null) {
+                    return;
+                }
+                populateList();
+            }
+        }.execute();
+    }
+
+    private void populateList() {
+        // TODO: if preference has children, compare with newly loaded list
+        mPreference.removeAll();
+
+        if (mChannelGroupList.isEmpty()) {
+            PreferenceCategory groupCategory = new PreferenceCategory(mContext);
+            groupCategory.setTitle(R.string.notification_channels);
+            groupCategory.setKey(KEY_GENERAL_CATEGORY);
+            mPreference.addPreference(groupCategory);
+
+            Preference empty = new Preference(mContext);
+            empty.setTitle(R.string.no_channels);
+            empty.setEnabled(false);
+            groupCategory.addPreference(empty);
+        } else {
+            populateGroupList();
+        }
+    }
+
+    private void populateGroupList() {
+        for (NotificationChannelGroup group : mChannelGroupList) {
+            PreferenceCategory groupCategory = new PreferenceCategory(mContext);
+            groupCategory.setOrderingAsAdded(true);
+            mPreference.addPreference(groupCategory);
+            if (group.getId() == null) {
+                if (mChannelGroupList.size() > 1) {
+                    groupCategory.setTitle(R.string.notification_channels_other);
+                }
+                groupCategory.setKey(KEY_GENERAL_CATEGORY);
+            } else {
+                groupCategory.setTitle(group.getName());
+                groupCategory.setKey(group.getId());
+                populateGroupToggle(groupCategory, group);
+            }
+            if (!group.isBlocked()) {
+                final List<NotificationChannel> channels = group.getChannels();
+                Collections.sort(channels, mChannelComparator);
+                int N = channels.size();
+                for (int i = 0; i < N; i++) {
+                    final NotificationChannel channel = channels.get(i);
+                    populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
+                }
+            }
+        }
+    }
+
+    protected void populateGroupToggle(final PreferenceGroup parent,
+            NotificationChannelGroup group) {
+        RestrictedSwitchPreference preference =
+                new RestrictedSwitchPreference(mContext);
+        preference.setTitle(R.string.notification_switch_label);
+        preference.setEnabled(mAdmin == null
+                && isChannelGroupBlockable(group));
+        preference.setChecked(!group.isBlocked());
+        preference.setOnPreferenceClickListener(preference1 -> {
+            final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
+            group.setBlocked(!allowGroup);
+            mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
+
+            onGroupBlockStateChanged(group);
+            return true;
+        });
+
+        parent.addPreference(preference);
+    }
+
+    protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
+            final NotificationChannel channel, final boolean groupBlocked) {
+        MasterSwitchPreference channelPref = new MasterSwitchPreference(mContext);
+        channelPref.setSwitchEnabled(mAdmin == null
+                && isChannelBlockable(channel)
+                && isChannelConfigurable(channel)
+                && !groupBlocked);
+        channelPref.setIcon(null);
+        if (channel.getImportance() > IMPORTANCE_LOW) {
+            channelPref.setIcon(getAlertingIcon());
+        }
+        channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
+        channelPref.setKey(channel.getId());
+        channelPref.setTitle(channel.getName());
+        channelPref.setSummary(NotificationBackend.getSentSummary(
+                mContext, mAppRow.sentByChannel.get(channel.getId()), false));
+        channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
+        Bundle channelArgs = new Bundle();
+        channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
+        channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
+        channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
+        channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
+        channelPref.setIntent(new SubSettingLauncher(mContext)
+                .setDestination(ChannelNotificationSettings.class.getName())
+                .setArguments(channelArgs)
+                .setTitleRes(R.string.notification_channel_title)
+                .setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
+                .toIntent());
+
+        channelPref.setOnPreferenceChangeListener(
+                (preference, o) -> {
+                    boolean value = (Boolean) o;
+                    int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
+                    channel.setImportance(importance);
+                    channel.lockFields(
+                            NotificationChannel.USER_LOCKED_IMPORTANCE);
+                    MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
+                    channelPref1.setIcon(null);
+                    if (channel.getImportance() > IMPORTANCE_LOW) {
+                        channelPref1.setIcon(getAlertingIcon());
+                    }
+                    toggleBehaviorIconState(channelPref1.getIcon(),
+                            importance != IMPORTANCE_NONE);
+                    mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, channel);
+
+                    return true;
+                });
+        if (parent.findPreference(channelPref.getKey()) == null) {
+            parent.addPreference(channelPref);
+        }
+        return channelPref;
+    }
+
+    private Drawable getAlertingIcon() {
+        Drawable icon = mContext.getDrawable(R.drawable.ic_notifications_alert);
+        icon.setTintList(Utils.getColorAccent(mContext));
+        return icon;
+    }
+
+    private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
+        if (icon == null) return;
+
+        LayerDrawable layerDrawable = (LayerDrawable) icon;
+        GradientDrawable background =
+                (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
+
+        if (background == null) return;
+
+        if (enabled) {
+            background.clearColorFilter();
+        } else {
+            background.setColorFilter(new BlendModeColorFilter(
+                    mContext.getColor(R.color.material_grey_300),
+                    BlendMode.SRC_IN));
+        }
+    }
+
+    protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
+        if (group == null) {
+            return;
+        }
+        PreferenceGroup groupGroup = mPreference.findPreference(group.getId());
+
+        if (groupGroup != null) {
+            if (group.isBlocked()) {
+                List<Preference> toRemove = new ArrayList<>();
+                int childCount = groupGroup.getPreferenceCount();
+                for (int i = 0; i < childCount; i++) {
+                    Preference pref = groupGroup.getPreference(i);
+                    if (pref instanceof MasterSwitchPreference) {
+                        toRemove.add(pref);
+                    }
+                }
+                for (Preference pref : toRemove) {
+                    groupGroup.removePreference(pref);
+                }
+            } else {
+                final List<NotificationChannel> channels = group.getChannels();
+                Collections.sort(channels, mChannelComparator);
+                int N = channels.size();
+                for (int i = 0; i < N; i++) {
+                    final NotificationChannel channel = channels.get(i);
+                    populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
+                }
+            }
+        }
+    }
+
+    private Comparator<NotificationChannelGroup> mChannelGroupComparator =
+            new Comparator<NotificationChannelGroup>() {
+
+                @Override
+                public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
+                    // Non-grouped channels (in placeholder group with a null id) come last
+                    if (left.getId() == null && right.getId() != null) {
+                        return 1;
+                    } else if (right.getId() == null && left.getId() != null) {
+                        return -1;
+                    }
+                    return left.getId().compareTo(right.getId());
+                }
+            };
+
+    protected Comparator<NotificationChannel> mChannelComparator =
+            (left, right) -> {
+                if (left.isDeleted() != right.isDeleted()) {
+                    return Boolean.compare(left.isDeleted(), right.isDeleted());
+                } else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+                    // Uncategorized/miscellaneous legacy channel goes last
+                    return 1;
+                } else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+                    return -1;
+                }
+
+                return left.getId().compareTo(right.getId());
+            };
+}
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index 8399a49..09bf0e2 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.notification;
 
+import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
+
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java
index 2ae7019..b5acd2d 100644
--- a/src/com/android/settings/notification/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationPreferenceController.java
@@ -113,25 +113,40 @@
     }
 
     protected boolean isChannelBlockable() {
-        if (mChannel != null && mAppRow != null) {
-            if (mChannel.isImportanceLockedByCriticalDeviceFunction()
-                    || mChannel.isImportanceLockedByOEM()) {
-                return mChannel.getImportance() == IMPORTANCE_NONE;
+        return isChannelBlockable(mChannel);
+    }
+
+    protected boolean isChannelBlockable(NotificationChannel channel) {
+        if (channel != null && mAppRow != null) {
+            if (channel.isImportanceLockedByCriticalDeviceFunction()
+                    || channel.isImportanceLockedByOEM()) {
+                return channel.getImportance() == IMPORTANCE_NONE;
             }
 
-            return mChannel.isBlockableSystem() || !mAppRow.systemApp
-                    || mChannel.getImportance() == IMPORTANCE_NONE;
+            return channel.isBlockableSystem() || !mAppRow.systemApp
+                    || channel.getImportance() == IMPORTANCE_NONE;
+        }
+        return false;
+    }
+
+    protected boolean isChannelConfigurable(NotificationChannel channel) {
+        if (channel != null && mAppRow != null) {
+            return !channel.isImportanceLockedByOEM();
         }
         return false;
     }
 
     protected boolean isChannelGroupBlockable() {
-        if (mChannelGroup != null && mAppRow != null) {
+        return isChannelGroupBlockable(mChannelGroup);
+    }
+
+    protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
+        if (group != null && mAppRow != null) {
             if (!mAppRow.systemApp) {
                 return true;
             }
 
-            return mChannelGroup.isBlocked();
+            return group.isBlocked();
         }
         return false;
     }
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index 2a728c5..27a2de0 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -67,7 +67,6 @@
 abstract public class NotificationSettingsBase extends DashboardFragment {
     private static final String TAG = "NotifiSettingsBase";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    public static final String ARG_FROM_SETTINGS = "fromSettings";
 
     protected PackageManager mPm;
     protected NotificationBackend mBackend = new NotificationBackend();
@@ -88,7 +87,6 @@
     protected boolean mListeningToPackageRemove;
 
     protected List<NotificationPreferenceController> mControllers = new ArrayList<>();
-    protected List<Preference> mDynamicPreferences = new ArrayList<>();
     protected ImportanceListener mImportanceListener = new ImportanceListener();
 
     protected Intent mIntent;
@@ -126,7 +124,6 @@
             mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
                     mContext, mPkg, mUserId);
 
-
             loadChannel();
             loadAppRow();
             loadChannelGroup();
@@ -280,135 +277,6 @@
         return null;
     }
 
-    private Drawable getAlertingIcon() {
-        Drawable icon = getContext().getDrawable(R.drawable.ic_notifications_alert);
-        icon.setTintList(Utils.getColorAccent(getContext()));
-        return icon;
-    }
-
-    protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
-            final NotificationChannel channel, final boolean groupBlocked) {
-        MasterSwitchPreference channelPref = new MasterSwitchPreference(getPrefContext());
-        channelPref.setSwitchEnabled(mSuspendedAppsAdmin == null
-                && isChannelBlockable(channel)
-                && isChannelConfigurable(channel)
-                && !groupBlocked);
-        channelPref.setIcon(null);
-        if (channel.getImportance() > IMPORTANCE_LOW) {
-            channelPref.setIcon(getAlertingIcon());
-        }
-        channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
-        channelPref.setKey(channel.getId());
-        channelPref.setTitle(channel.getName());
-        channelPref.setSummary(NotificationBackend.getSentSummary(
-                mContext, mAppRow.sentByChannel.get(channel.getId()), false));
-        channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
-        Bundle channelArgs = new Bundle();
-        channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
-        channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
-        channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
-        channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
-        channelPref.setIntent(new SubSettingLauncher(getActivity())
-                .setDestination(ChannelNotificationSettings.class.getName())
-                .setArguments(channelArgs)
-                .setTitleRes(R.string.notification_channel_title)
-                .setSourceMetricsCategory(getMetricsCategory())
-                .toIntent());
-
-        channelPref.setOnPreferenceChangeListener(
-                (preference, o) -> {
-                    boolean value = (Boolean) o;
-                    int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
-                    channel.setImportance(importance);
-                    channel.lockFields(
-                            NotificationChannel.USER_LOCKED_IMPORTANCE);
-                    MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
-                    channelPref1.setIcon(null);
-                    if (channel.getImportance() > IMPORTANCE_LOW) {
-                        channelPref1.setIcon(getAlertingIcon());
-                    }
-                    toggleBehaviorIconState(channelPref1.getIcon(),
-                            importance != IMPORTANCE_NONE);
-                    mBackend.updateChannel(mPkg, mUid, channel);
-
-                    return true;
-                });
-        if (parent.findPreference(channelPref.getKey()) == null) {
-            parent.addPreference(channelPref);
-        }
-        return channelPref;
-    }
-
-    private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
-        if (icon == null) return;
-
-        LayerDrawable layerDrawable = (LayerDrawable) icon;
-        GradientDrawable background =
-                (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
-
-        if (background == null) return;
-
-        if (enabled) {
-            background.clearColorFilter();
-        } else {
-            background.setColorFilter(new BlendModeColorFilter(
-                    mContext.getColor(R.color.material_grey_300),
-                    BlendMode.SRC_IN));
-        }
-    }
-
-    protected boolean isChannelConfigurable(NotificationChannel channel) {
-        if (channel != null && mAppRow != null) {
-            return !channel.isImportanceLockedByOEM();
-        }
-        return false;
-    }
-
-    protected boolean isChannelBlockable(NotificationChannel channel) {
-        if (channel != null && mAppRow != null) {
-            if (!mAppRow.systemApp) {
-                return true;
-            }
-
-            if (channel.isImportanceLockedByCriticalDeviceFunction()) {
-                return false;
-            }
-
-            if (channel.isImportanceLockedByOEM()) {
-                return false;
-            }
-
-            return channel.isBlockableSystem()
-                    || channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
-        }
-        return false;
-    }
-
-    protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
-        if (group != null && mAppRow != null) {
-            if (!mAppRow.systemApp) {
-                return true;
-            }
-
-            return group.isBlocked();
-        }
-        return false;
-    }
-
-    protected void setVisible(Preference p, boolean visible) {
-        setVisible(getPreferenceScreen(), p, visible);
-    }
-
-    protected void setVisible(PreferenceGroup parent, Preference p, boolean visible) {
-        final boolean isVisible = parent.findPreference(p.getKey()) != null;
-        if (isVisible == visible) return;
-        if (visible) {
-            parent.addPreference(p);
-        } else {
-            parent.removePreference(p);
-        }
-    }
-
     protected void startListeningToPackageRemove() {
         if (mListeningToPackageRemove) {
             return;
@@ -445,20 +313,6 @@
         }
     };
 
-    protected Comparator<NotificationChannel> mChannelComparator =
-            (left, right) -> {
-                if (left.isDeleted() != right.isDeleted()) {
-                    return Boolean.compare(left.isDeleted(), right.isDeleted());
-                } else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-                    // Uncategorized/miscellaneous legacy channel goes last
-                    return 1;
-                } else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-                    return -1;
-                }
-
-                return left.getId().compareTo(right.getId());
-            };
-
     protected class ImportanceListener {
         protected void onImportanceChanged() {
             final PreferenceScreen screen = getPreferenceScreen();
@@ -466,20 +320,6 @@
                 controller.displayPreference(screen);
             }
             updatePreferenceStates();
-
-            boolean hideDynamicFields = false;
-            if (mAppRow == null || mAppRow.banned) {
-                hideDynamicFields = true;
-            } else {
-                if (mChannel != null) {
-                    hideDynamicFields = mChannel.getImportance() == IMPORTANCE_NONE;
-                } else if (mChannelGroup != null) {
-                    hideDynamicFields = mChannelGroup.isBlocked();
-                }
-            }
-            for (Preference preference : mDynamicPreferences) {
-                setVisible(getPreferenceScreen(), preference, !hideDynamicFields);
-            }
         }
     }
 }
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 061a81e..5d4abad 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -51,7 +51,6 @@
 com.android.settings.network.ApnSettings
 com.android.settings.network.telephony.NetworkSelectSettings
 com.android.settings.notification.AppNotificationSettings
-com.android.settings.notification.ChannelGroupNotificationSettings
 com.android.settings.notification.ChannelNotificationSettings
 com.android.settings.notification.NotificationStation
 com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment