Show app level settings when app doesn't use topics.

Change-Id: I3c31a1bdddc70077182ea910911de1444472b7a9
diff --git a/res/layout/preference_importance_slider.xml b/res/layout/preference_importance_slider.xml
index d7d04b4..0099384 100644
--- a/res/layout/preference_importance_slider.xml
+++ b/res/layout/preference_importance_slider.xml
@@ -58,7 +58,8 @@
                     android:src="@*android:drawable/ic_notification_block"
                     android:layout_gravity="center_vertical|start"
                     android:layout_width="24dp"
-                    android:layout_height="24dp" />
+                    android:layout_height="24dp"
+                    android:tint="@color/importance_icon_tint" />
 
             <SeekBar
                     android:id="@*android:id/seekbar"
@@ -66,7 +67,7 @@
                     android:layout_marginEnd="56dp"
                     android:layout_gravity="center_vertical"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
+                    android:layout_height="48dp"
                     android:focusable="true"
                     android:background="#00ffffff"
                     style="@android:style/Widget.Material.SeekBar.Discrete"
@@ -77,7 +78,8 @@
                     android:src="@*android:drawable/ic_notification_alert"
                     android:layout_gravity="center_vertical|end"
                     android:layout_width="24dp"
-                    android:layout_height="24dp" />
+                    android:layout_height="24dp"
+                    android:tint="@color/importance_icon_tint" />
 
         </FrameLayout>
 
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 60c15d7..579cd9e 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -104,6 +104,9 @@
     <color name="summary_default_start">#ff009587</color>
     <color name="summary_default_end">#ffced7db</color>
 
+    <color name="importance_icon_tint">#8a000000</color>
+    <color name="importance_disabled_tint">#4d000000</color>
+
     <!-- Accessibility SUW colors -->
     <color name="material_blue_500">#4285F4</color>
     <color name="material_blue_700">#3367D6</color>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index 5f00caf..3141af8 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -18,24 +18,10 @@
         android:title="@string/app_notifications_title"
         android:key="app_notification_settings">
 
-    <!-- Block -->
-    <SwitchPreference
-            android:key="block"
-            android:title="@string/app_notification_block_title"
-            android:summary="@string/app_notification_block_summary"
-            android:order="1"
-            android:persistent="false" />
-
-    <!-- App notification preferences -->
+     <!-- App notification preferences -->
     <Preference
             android:key="app_settings"
             android:title="@string/app_notification_preferences"
-            android:order="2"
             android:persistent="false" />
 
-    <PreferenceCategory
-            android:key="categories"
-            android:title="@string/notification_topic_categories"
-            android:order="3" />
-
 </PreferenceScreen>
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 9add4eb..a583249 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -17,33 +17,23 @@
 package com.android.settings.notification;
 
 import android.app.Notification;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
-import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
 import android.support.v7.preference.PreferenceCategory;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.AppHeader;
 import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.notification.NotificationBackend.AppRow;
@@ -51,7 +41,7 @@
 import java.util.List;
 
 /** These settings are per app, so should not be returned in global search results. */
-public class AppNotificationSettings extends SettingsPreferenceFragment {
+public class AppNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "AppNotificationSettings";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -63,24 +53,13 @@
             = new Intent(Intent.ACTION_MAIN)
                 .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
 
-    private final NotificationBackend mBackend = new NotificationBackend();
-
-    private Context mContext;
     private SwitchPreference mBlock;
     private PreferenceCategory mCategories;
     private AppRow mAppRow;
-    private boolean mCreated;
-    private int mUid;
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
-        if (mCreated) {
-            Log.w(TAG, "onActivityCreated: ignoring duplicate call");
-            return;
-        }
-        mCreated = true;
         if (mAppRow == null) return;
         AppHeader.createAppHeader(this, mAppRow.icon, mAppRow.label, mAppRow.pkg, mAppRow.uid);
     }
@@ -93,86 +72,48 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mContext = getActivity();
-        Intent intent = getActivity().getIntent();
-        Bundle args = getArguments();
-        if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
-        if (intent == null && args == null) {
-            Log.w(TAG, "No intent");
-            toastAndFinish();
-            return;
-        }
 
-        final String pkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
-                ? args.getString(AppInfoBase.ARG_PACKAGE_NAME)
-                : intent.getStringExtra(Settings.EXTRA_APP_PACKAGE);
-        mUid = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_UID)
-                ? args.getInt(AppInfoBase.ARG_PACKAGE_UID)
-                : intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
-        if (mUid == -1 || TextUtils.isEmpty(pkg)) {
-            Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_PACKAGE + " was " + pkg + ", "
-                    + Settings.EXTRA_APP_UID + " was " + mUid);
-            toastAndFinish();
-            return;
-        }
-
-        if (DEBUG) Log.d(TAG, "Load details for pkg=" + pkg + " uid=" + mUid);
-        final PackageManager pm = getPackageManager();
-        final PackageInfo info = findPackageInfo(pm, pkg, mUid);
-        if (info == null) {
-            Log.w(TAG, "Failed to find package info: " + Settings.EXTRA_APP_PACKAGE + " was " + pkg
-                    + ", " + Settings.EXTRA_APP_UID + " was " + mUid);
-            toastAndFinish();
-            return;
-        }
         addPreferencesFromResource(R.xml.app_notification_settings);
-        mBlock = (SwitchPreference) findPreference(KEY_BLOCK);
-
-        mAppRow = mBackend.loadAppRow(pm, info);
+        getPreferenceScreen().setOrderingAsAdded(true);
+        mAppRow = mBackend.loadAppRow(mPm, mPkgInfo);
 
         // load settings intent
         ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
         rows.put(mAppRow.pkg, mAppRow);
-        collectConfigActivities(getPackageManager(), rows);
+        collectConfigActivities(rows);
 
         // Add topics
-        List<Notification.Topic> topics = mBackend.getTopics(pkg, mUid);
-        mCategories = (PreferenceCategory) getPreferenceScreen().findPreference(KEY_CATEGORIES);
-        for (Notification.Topic topic : topics) {
-            Preference topicPreference = new Preference(mContext);
-            topicPreference.setKey(topic.getId());
-            topicPreference.setTitle(topic.getLabel());
-            // Create intent for this preference.
-            Bundle topicArgs = new Bundle();
-            topicArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
-            topicArgs.putParcelable(TopicNotificationSettings.ARG_TOPIC, topic);
-            topicArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
-            topicArgs.putParcelable(TopicNotificationSettings.ARG_PACKAGE_INFO, info);
+        List<Notification.Topic> topics = mBackend.getTopics(mPkg, mUid);
+        if (topics.size() <= 1) {
+            setupImportancePref(mAppRow, null, mAppRow.appImportance);
+            setupPriorityPref(null, mAppRow.appBypassDnd);
+            setupSensitivePref(null, mAppRow.appSensitive);
+        } else {
+            setupBlockSwitch();
+            mCategories = new PreferenceCategory(getPrefContext());
+            mCategories.setKey(KEY_CATEGORIES);
+            mCategories.setTitle(R.string.notification_topic_categories);
+            mCategories.setOrderingAsAdded(true);
+            getPreferenceScreen().addPreference(mCategories);
+            for (Notification.Topic topic : topics) {
+                Preference topicPreference = new Preference(getPrefContext());
+                topicPreference.setKey(topic.getId());
+                topicPreference.setTitle(topic.getLabel());
+                // Create intent for this preference.
+                Bundle topicArgs = new Bundle();
+                topicArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
+                topicArgs.putParcelable(TopicNotificationSettings.ARG_TOPIC, topic);
+                topicArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
+                topicArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
+                topicArgs.putParcelable(TopicNotificationSettings.ARG_PACKAGE_INFO, mPkgInfo);
 
-            Intent topicIntent = Utils.onBuildStartFragmentIntent(getActivity(),
-                    TopicNotificationSettings.class.getName(),
-                    topicArgs, null, R.string.topic_notifications_title, null, false);
-            topicPreference.setIntent(topicIntent);
-            mCategories.addPreference(topicPreference);
-        }
-
-        mBlock.setChecked(mAppRow.banned);
-        updateDependents(mAppRow.systemApp, mAppRow.banned);
-
-        mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean banned = (Boolean) newValue;
-                if (banned) {
-                    MetricsLogger.action(getActivity(), MetricsLogger.ACTION_BAN_APP_NOTES, pkg);
-                }
-                final boolean success =  mBackend.setNotificationsBanned(pkg, mUid, banned);
-                if (success) {
-                    updateDependents(mAppRow.systemApp, banned);
-                }
-                return success;
+                Intent topicIntent = Utils.onBuildStartFragmentIntent(getActivity(),
+                        TopicNotificationSettings.class.getName(),
+                        topicArgs, null, R.string.topic_notifications_title, null, false);
+                topicPreference.setIntent(topicIntent);
+                mCategories.addPreference(topicPreference);
             }
-        });
+        }
 
         if (mAppRow.settingsIntent != null) {
             findPreference(KEY_APP_SETTINGS).setOnPreferenceClickListener(
@@ -189,70 +130,59 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        if (mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null) {
-            // App isn't around anymore, must have been removed.
-            finish();
-        }
+    protected void updateDependents(int progress) {
+        updateDependents(progress == NotificationListenerService.Ranking.IMPORTANCE_NONE);
     }
 
-    private void updateDependents(boolean isSystemPackage, boolean banned) {
-        setVisible(mBlock, !isSystemPackage);
+    private void updateDependents(boolean banned) {
+        if (mBlock != null) {
+            mBlock.setEnabled(!mAppRow.systemApp);
+        }
         if (mCategories != null) {
             setVisible(mCategories, !banned);
         }
     }
 
-    private void setVisible(Preference p, boolean visible) {
-        final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
-        if (isVisible == visible) return;
-        if (visible) {
-            getPreferenceScreen().addPreference(p);
-        } else {
-            getPreferenceScreen().removePreference(p);
-        }
-    }
-
-    private void toastAndFinish() {
-        Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
-        getActivity().finish();
-    }
-
-    private static PackageInfo findPackageInfo(PackageManager pm, String pkg, int uid) {
-        final String[] packages = pm.getPackagesForUid(uid);
-        if (packages != null && pkg != null) {
-            final int N = packages.length;
-            for (int i = 0; i < N; i++) {
-                final String p = packages[i];
-                if (pkg.equals(p)) {
-                    try {
-                        return pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
-                    } catch (NameNotFoundException e) {
-                        Log.w(TAG, "Failed to load package " + pkg, e);
-                    }
+    private void setupBlockSwitch() {
+        mBlock = new SwitchPreference(getPrefContext());
+        mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                final boolean banned = (Boolean) newValue;
+                if (banned) {
+                    MetricsLogger.action(getActivity(), MetricsLogger.ACTION_BAN_APP_NOTES, mPkg);
                 }
+                final boolean success =  mBackend.setNotificationsBanned(mPkg, mUid, banned);
+                if (success) {
+                    updateDependents(banned);
+                }
+                return success;
             }
-        }
-        return null;
+        });
+        mBlock.setKey(KEY_BLOCK);
+        mBlock.setTitle(R.string.app_notification_block_title);
+        mBlock.setSummary(R.string.app_notification_block_summary);
+        getPreferenceScreen().addPreference(mBlock);
+        mBlock.setChecked(mAppRow.banned);
+        updateDependents(mAppRow.banned);
     }
 
-    public static List<ResolveInfo> queryNotificationConfigActivities(PackageManager pm) {
+    private List<ResolveInfo> queryNotificationConfigActivities() {
         if (DEBUG) Log.d(TAG, "APP_NOTIFICATION_PREFS_CATEGORY_INTENT is "
                 + APP_NOTIFICATION_PREFS_CATEGORY_INTENT);
-        final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
+        final List<ResolveInfo> resolveInfos = mPm.queryIntentActivities(
                 APP_NOTIFICATION_PREFS_CATEGORY_INTENT,
                 0 //PackageManager.MATCH_DEFAULT_ONLY
         );
         return resolveInfos;
     }
 
-    public static void collectConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows) {
-        final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities(pm);
-        applyConfigActivities(pm, rows, resolveInfos);
+    private void collectConfigActivities(ArrayMap<String, AppRow> rows) {
+        final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities();
+        applyConfigActivities(rows, resolveInfos);
     }
 
-    public static void applyConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows,
+    private void applyConfigActivities(ArrayMap<String, AppRow> rows,
             List<ResolveInfo> resolveInfos) {
         if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities"
                 + (resolveInfos.size() == 0 ? " ;_;" : ""));
diff --git a/src/com/android/settings/notification/ImportanceSeekBarPreference.java b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
index 190a9ab..920fcc3 100644
--- a/src/com/android/settings/notification/ImportanceSeekBarPreference.java
+++ b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
@@ -23,6 +23,7 @@
 import android.service.notification.NotificationListenerService;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
+import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.TextView;
 
@@ -37,6 +38,7 @@
     private TextView mSummaryTextView;
     private String mSummary;
     private int mMinProgress;
+    private boolean mSystemApp;
 
     public ImportanceSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
@@ -64,10 +66,19 @@
         mMinProgress = minProgress;
     }
 
+    public void setSystemApp(boolean systemApp) {
+        mSystemApp = systemApp;
+        notifyChanged();
+    }
+
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
         mSummaryTextView = (TextView) view.findViewById(com.android.internal.R.id.summary);
+        if (mSystemApp) {
+            ((ImageView) view.findViewById(R.id.low_importance)).getDrawable().setTint(
+                    getContext().getColor(R.color.importance_disabled_tint));
+        }
     }
 
     @Override
@@ -83,8 +94,9 @@
             seekBar.setProgress(mMinProgress);
             progress = mMinProgress;
         }
+        mSummary = getProgressSummary(progress);
         if (mSummaryTextView != null) {
-            mSummaryTextView.setText(getProgressSummary(progress));
+            mSummaryTextView.setText(mSummary);
         }
         if (fromTouch) {
             mCallback.onImportanceChanged(progress);
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index d37ccca..292d247 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -51,6 +51,9 @@
         }
         row.icon = app.loadIcon(pm);
         row.banned = getNotificationsBanned(row.pkg, row.uid);
+        row.appImportance = getImportance(row.pkg, row.uid, null);
+        row.appBypassDnd = getBypassZenMode(row.pkg, row.uid, null);
+        row.appSensitive = getSensitive(row.pkg, row.uid, null);
         return row;
     }
 
@@ -97,7 +100,7 @@
 
     public boolean getBypassZenMode(String pkg, int uid, Notification.Topic topic) {
         try {
-            return sINM.getTopicPriority(pkg, uid, topic) == Notification.PRIORITY_MAX;
+            return sINM.getPriority(pkg, uid, topic) == Notification.PRIORITY_MAX;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
             return false;
@@ -107,7 +110,7 @@
     public boolean setBypassZenMode(String pkg, int uid, Notification.Topic topic,
             boolean bypassZen) {
         try {
-            sINM.setTopicPriority(pkg, uid, topic,
+            sINM.setPriority(pkg, uid, topic,
                     bypassZen ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT);
             return true;
         } catch (Exception e) {
@@ -118,7 +121,7 @@
 
     public boolean getSensitive(String pkg, int uid, Notification.Topic topic) {
         try {
-            return sINM.getTopicVisibilityOverride(pkg, uid, topic)
+            return sINM.getVisibilityOverride(pkg, uid, topic)
                     == Notification.VISIBILITY_PRIVATE;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
@@ -128,7 +131,7 @@
 
     public boolean setSensitive(String pkg, int uid, Notification.Topic topic, boolean sensitive) {
         try {
-            sINM.setTopicVisibilityOverride(pkg, uid, topic,
+            sINM.setVisibilityOverride(pkg, uid, topic,
                     sensitive ? Notification.VISIBILITY_PRIVATE
                             : NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
             return true;
@@ -140,7 +143,7 @@
 
     public boolean setImportance(String pkg, int uid, Notification.Topic topic, int importance) {
         try {
-            sINM.setTopicImportance(pkg, uid, topic, importance);
+            sINM.setImportance(pkg, uid, topic, importance);
             return true;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
@@ -150,7 +153,7 @@
 
     public int getImportance(String pkg, int uid, Notification.Topic topic) {
         try {
-            return sINM.getTopicImportance(pkg, uid, topic);
+            return sINM.getImportance(pkg, uid, topic);
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
             return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
@@ -180,6 +183,9 @@
         public boolean banned;
         public boolean first;  // first app in section
         public boolean systemApp;
+        public int appImportance;
+        public boolean appBypassDnd;
+        public boolean appSensitive;
     }
 
     public static class TopicRow extends AppRow {
@@ -188,5 +194,4 @@
         public boolean sensitive;
         public int importance;
     }
-
 }
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
new file mode 100644
index 0000000..a669d95
--- /dev/null
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 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 com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.applications.AppInfoBase;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+abstract public class NotificationSettingsBase extends SettingsPreferenceFragment {
+    private static final String TAG = "NotifiSettingsBase";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    protected static final String ARG_PACKAGE_INFO = "arg_info";
+
+    protected static final String KEY_BYPASS_DND = "bypass_dnd";
+    protected static final String KEY_SENSITIVE = "sensitive";
+    protected static final String KEY_IMPORTANCE = "importance";
+
+    protected PackageManager mPm;
+    protected final NotificationBackend mBackend = new NotificationBackend();
+    protected Context mContext;
+    protected boolean mCreated;
+    protected int mUid;
+    protected String mPkg;
+    protected PackageInfo mPkgInfo;
+    protected ImportanceSeekBarPreference mImportance;
+    protected SwitchPreference mPriority;
+    protected SwitchPreference mSensitive;
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
+        if (mCreated) {
+            Log.w(TAG, "onActivityCreated: ignoring duplicate call");
+            return;
+        }
+        mCreated = true;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getActivity();
+        Intent intent = getActivity().getIntent();
+        Bundle args = getArguments();
+        if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
+        if (intent == null && args == null) {
+            Log.w(TAG, "No intent");
+            toastAndFinish();
+            return;
+        }
+
+        mPm = getPackageManager();
+
+        mPkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
+                ? args.getString(AppInfoBase.ARG_PACKAGE_NAME)
+                : intent.getStringExtra(Settings.EXTRA_APP_PACKAGE);
+        mUid = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_UID)
+                ? args.getInt(AppInfoBase.ARG_PACKAGE_UID)
+                : intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
+        if (mUid == -1 || TextUtils.isEmpty(mPkg)) {
+            Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_PACKAGE + " was " + mPkg + ", "
+                    + Settings.EXTRA_APP_UID + " was " + mUid);
+            toastAndFinish();
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "Load details for pkg=" + mPkg + " uid=" + mUid);
+        mPkgInfo = args != null && args.containsKey(ARG_PACKAGE_INFO)
+                ? (PackageInfo) args.getParcelable(ARG_PACKAGE_INFO) : null;
+        if (mPkgInfo == null) {
+            mPkgInfo = findPackageInfo(mPkg, mUid);
+        }
+        if (mPkgInfo == null) {
+            Log.w(TAG, "Failed to find package info: " + Settings.EXTRA_APP_PACKAGE + " was " + mPkg
+                    + ", " + Settings.EXTRA_APP_UID + " was " + mUid);
+            toastAndFinish();
+            return;
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null) {
+            // App isn't around anymore, must have been removed.
+            finish();
+        }
+    }
+
+    protected void setupImportancePref(final NotificationBackend.AppRow appRow,
+            final Notification.Topic topic, int importance) {
+        if (mImportance == null) {
+            mImportance = new ImportanceSeekBarPreference(getPrefContext());
+            mImportance.setTitle(R.string.notification_importance_title);
+            mImportance.setKey(KEY_IMPORTANCE);
+            getPreferenceScreen().addPreference(mImportance);
+        }
+        mImportance.setSystemApp(appRow.systemApp);
+        mImportance.setMinimumProgress(
+                appRow.systemApp ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_NONE);
+        mImportance.setMax(Ranking.IMPORTANCE_MAX);
+        // TODO: stop defaulting to 'normal' in the UI when there are mocks for this scenario.
+        importance = importance == Ranking.IMPORTANCE_UNSPECIFIED
+                        ? Ranking.IMPORTANCE_DEFAULT
+                        : importance;
+        mImportance.setProgress(importance);
+        mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
+            @Override
+            public void onImportanceChanged(int progress) {
+                mBackend.setImportance(appRow.pkg, appRow.uid, topic, progress);
+                updateDependents(progress);
+            }
+        });
+    }
+
+    protected void setupPriorityPref(final Notification.Topic topic, boolean priority) {
+        if (mPriority == null) {
+            mPriority = new SwitchPreference(getPrefContext());
+            mPriority.setTitle(R.string.app_notification_override_dnd_title);
+            mPriority.setSummary(R.string.app_notification_override_dnd_summary);
+            mPriority.setKey(KEY_BYPASS_DND);
+            getPreferenceScreen().addPreference(mPriority);
+        }
+        mPriority.setChecked(priority);
+        mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                final boolean bypassZenMode = (Boolean) newValue;
+                return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, topic, bypassZenMode);
+            }
+        });
+    }
+
+    protected void setupSensitivePref(final Notification.Topic topic, boolean sensitive) {
+        if (mSensitive == null) {
+            mSensitive = new SwitchPreference(getPrefContext());
+            mSensitive.setTitle(R.string.app_notification_sensitive_title);
+            mSensitive.setSummary(R.string.app_notification_sensitive_summary);
+            mSensitive.setKey(KEY_SENSITIVE);
+            getPreferenceScreen().addPreference(mSensitive);
+        }
+        mSensitive.setChecked(sensitive);
+        mSensitive.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                final boolean sensitive = (Boolean) newValue;
+                return mBackend.setSensitive(mPkgInfo.packageName, mUid, topic, sensitive);
+            }
+        });
+    }
+
+    abstract void updateDependents(int progress);
+
+    protected void setVisible(Preference p, boolean visible) {
+        final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
+        if (isVisible == visible) return;
+        if (visible) {
+            getPreferenceScreen().addPreference(p);
+        } else {
+            getPreferenceScreen().removePreference(p);
+        }
+    }
+
+    protected void toastAndFinish() {
+        Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
+        getActivity().finish();
+    }
+
+    private PackageInfo findPackageInfo(String pkg, int uid) {
+        final String[] packages = mPm.getPackagesForUid(uid);
+        if (packages != null && pkg != null) {
+            final int N = packages.length;
+            for (int i = 0; i < N; i++) {
+                final String p = packages[i];
+                if (pkg.equals(p)) {
+                    try {
+                        return mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+                    } catch (NameNotFoundException e) {
+                        Log.w(TAG, "Failed to load package " + pkg, e);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/notification/TopicNotificationSettings.java b/src/com/android/settings/notification/TopicNotificationSettings.java
index f2cbf1a..52e7f65 100644
--- a/src/com/android/settings/notification/TopicNotificationSettings.java
+++ b/src/com/android/settings/notification/TopicNotificationSettings.java
@@ -42,36 +42,17 @@
 import android.widget.Toast;
 
 /** These settings are per topic, so should not be returned in global search results. */
-public class TopicNotificationSettings extends SettingsPreferenceFragment {
+public class TopicNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "TopicNotiSettings";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     protected static final String ARG_TOPIC = "arg_topic";
-    protected static final String ARG_PACKAGE_INFO = "arg_info";
-    private static final String KEY_BYPASS_DND = "bypass_dnd";
-    private static final String KEY_SENSITIVE = "sensitive";
-    private static final String KEY_IMPORTANCE = "importance";
 
-    private final NotificationBackend mBackend = new NotificationBackend();
-
-    private Context mContext;
-    private ImportanceSeekBarPreference mImportance;
-    private SwitchPreference mPriority;
-    private SwitchPreference mSensitive;
     private TopicRow mTopicRow;
-    private boolean mCreated;
-    private int mUid;
     private boolean mDndVisualEffectsSuppressed;
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
-        if (mCreated) {
-            Log.w(TAG, "onActivityCreated: ignoring duplicate call");
-            return;
-        }
-        mCreated = true;
         if (mTopicRow == null) return;
         AppHeader.createAppHeader(
                 this, mTopicRow.icon, mTopicRow.label, mTopicRow.pkg, mTopicRow.uid);
@@ -85,102 +66,36 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mContext = getActivity();
-        Intent intent = getActivity().getIntent();
-        Bundle args = getArguments();
-        if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
-        if (intent == null && args == null) {
-            Log.w(TAG, "No intent");
-            toastAndFinish();
-            return;
-        }
 
         NotificationManager.Policy policy =
                 NotificationManager.from(mContext).getNotificationPolicy();
         mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0;
 
+        Bundle args = getArguments();
         final Notification.Topic topic = args != null && args.containsKey(ARG_TOPIC)
                 ? (Notification.Topic) args.getParcelable(ARG_TOPIC) : null;
-
         if (topic == null) {
             toastAndFinish();
             return;
         }
 
-        final PackageInfo info = args != null && args.containsKey(ARG_PACKAGE_INFO)
-                ? (PackageInfo) args.getParcelable(ARG_PACKAGE_INFO) : null;
-        if (info == null) {
-            Log.w(TAG, "Failed to find package info");
-            toastAndFinish();
-            return;
-        }
-
-        mUid = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_UID)
-                ? args.getInt(AppInfoBase.ARG_PACKAGE_UID)
-                : intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
-        if (mUid == -1) {
-            Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_UID + " was " + mUid);
-            toastAndFinish();
-            return;
-        }
-
-        final PackageManager pm = getPackageManager();
-
         addPreferencesFromResource(R.xml.topic_notification_settings);
+        mTopicRow = mBackend.loadTopicRow(mPm, mPkgInfo, topic);
+
         mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
+        setupImportancePref(mTopicRow, mTopicRow.topic, mTopicRow.importance);
+
         mPriority = (SwitchPreference) findPreference(KEY_BYPASS_DND);
+        setupPriorityPref(mTopicRow.topic, mTopicRow.priority);
+
         mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
+        setupSensitivePref(mTopicRow.topic, mTopicRow.sensitive);
 
-        mTopicRow = mBackend.loadTopicRow(pm, info, topic);
-
-        mImportance.setMinimumProgress(
-                mTopicRow.systemApp ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_NONE);
-        mImportance.setMax(Ranking.IMPORTANCE_MAX);
-        // TODO: stop defaulting to 'normal' in the UI when there are mocks for this scenario.
-        int importance =
-                mTopicRow.importance == NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED
-                ? NotificationListenerService.Ranking.IMPORTANCE_DEFAULT
-                        : mTopicRow.importance;
-        mImportance.setProgress(importance);
-        mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
-            @Override
-            public void onImportanceChanged(int progress) {
-                mBackend.setImportance(mTopicRow.pkg, mTopicRow.uid, mTopicRow.topic, progress);
-                updateDependents(progress);
-            }
-        });
-        mPriority.setChecked(mTopicRow.priority);
-        mSensitive.setChecked(mTopicRow.sensitive);
-
-        mPriority.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean bypassZenMode = (Boolean) newValue;
-                return mBackend.setBypassZenMode(info.packageName, mUid, topic, bypassZenMode);
-            }
-        });
-
-        mSensitive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean sensitive = (Boolean) newValue;
-                return mBackend.setSensitive(info.packageName, mUid, topic, sensitive);
-            }
-        });
         updateDependents(mTopicRow.importance);
-
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        if (mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null) {
-            // App isn't around anymore, must have been removed.
-            finish();
-        }
-    }
-
-    private void updateDependents(int importance) {
+    protected void updateDependents(int importance) {
         final boolean lockscreenSecure = new LockPatternUtils(getActivity()).isSecure(
                 UserHandle.myUserId());
         final boolean lockscreenNotificationsEnabled = getLockscreenNotificationsEnabled();
@@ -193,16 +108,6 @@
                 && lockscreenSecure && lockscreenNotificationsEnabled && allowPrivate);
     }
 
-    private void setVisible(Preference p, boolean visible) {
-        final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null;
-        if (isVisible == visible) return;
-        if (visible) {
-            getPreferenceScreen().addPreference(p);
-        } else {
-            getPreferenceScreen().removePreference(p);
-        }
-    }
-
     private boolean getLockscreenNotificationsEnabled() {
         return Settings.Secure.getInt(getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
@@ -212,9 +117,4 @@
         return Settings.Secure.getInt(getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
     }
-
-    private void toastAndFinish() {
-        Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
-        getActivity().finish();
-    }
 }