Merge "Migrate package level notification settings to topic level."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index db986f1..8614d7a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6011,6 +6011,9 @@
     <!-- Sound & notification > Notification section: Title for the option managing notifications per application. [CHAR LIMIT=30] -->
     <string name="app_notifications_title">App notifications</string>
 
+    <!-- Sound & notification > Notification section: Title for the option managing notifications per topic. [CHAR LIMIT=30] -->
+    <string name="topic_notifications_title">Topic notifications</string>
+
     <!-- Sound & notification > Sound section: Title for the other sounds option and associated settings page. [CHAR LIMIT=30] -->
     <string name="other_sound_settings">Other sounds</string>
 
@@ -6093,17 +6096,17 @@
     <!-- [CHAR LIMIT=NONE] App notification settings: Block option description-->
     <string name="app_notification_block_summary">Never show notifications from this app</string>
 
-    <!-- [CHAR LIMIT=NONE] App notification settings: Priority option title -->
-    <string name="app_notification_priority_title">Treat as priority</string>
+    <!-- [CHAR LIMIT=NONE] App notification settings: Override DND option title -->
+    <string name="app_notification_override_dnd_title">Override Do Not Disturb</string>
 
-    <!-- [CHAR LIMIT=NONE] App notification settings: Priority option description-->
-    <string name="app_notification_priority_summary">Let this app\u2019s notifications be heard when Do not disturb is set to Priority only</string>
+    <!-- [CHAR LIMIT=NONE] App notification settings: Override DND option description-->
+    <string name="app_notification_override_dnd_summary">Let these notifications continue to interrupt when Do Not Disturb is set to Priority Only</string>
 
     <!-- [CHAR LIMIT=NONE] App notification settings: Sensitive option title -->
     <string name="app_notification_sensitive_title">Hide sensitive content</string>
 
     <!-- [CHAR LIMIT=NONE] App notification settings: Sensitive option description-->
-    <string name="app_notification_sensitive_summary">When the device is locked, hide content in this app\u2019s notifications that might reveal private information</string>
+    <string name="app_notification_sensitive_summary">When the device is locked, hide content in these notifications that might reveal private information</string>
 
     <!-- [CHAR LIMIT=20] Notification settings: App notifications row summary when banned -->
     <string name="app_notification_row_banned">Blocked</string>
@@ -6484,10 +6487,6 @@
    <string name="notifications_enabled">Normal</string>
    <!-- App notification summary with notifications disabled [CHAR LIMIT=40] -->
    <string name="notifications_disabled">Block</string>
-   <!-- App notification summary with notifications sensitive [CHAR LIMIT=40] -->
-   <string name="notifications_sensitive">Sensitive content hidden</string>
-   <!-- App notification summary with notifications priority [CHAR LIMIT=40] -->
-   <string name="notifications_priority">Priority</string>
    <!-- App notification summary with 2 items [CHAR LIMIT=15] -->
    <string name="notifications_two_items"><xliff:g id="notif_state" example="Priority">%1$s</xliff:g> / <xliff:g id="notif_state" example="Priority">%2$s</xliff:g></string>
    <!-- App notification summary with 3 items [CHAR LIMIT=15] -->
@@ -6528,10 +6527,6 @@
     <string name="filter_work_apps">Work</string>
     <!-- Label for showing apps with blocked notifications in list [CHAR LIMIT=30] -->
     <string name="filter_notif_blocked_apps">Blocked</string>
-    <!-- Label for showing apps with priority notifications in list [CHAR LIMIT=30] -->
-    <string name="filter_notif_priority_apps">Priority</string>
-    <!-- Label for showing apps with sensitive notifications in list [CHAR LIMIT=30] -->
-    <string name="filter_notif_sensitive_apps">Sensitive content hidden</string>
     <!-- Label for showing apps with domain URLs (data URI with http or https) in list [CHAR LIMIT=30] -->
     <string name="filter_with_domain_urls_apps">With domain URLs</string>
 
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index 149b9fc..6e27a07 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -26,22 +26,6 @@
             android:order="1"
             android:persistent="false" />
 
-    <!-- Priority -->
-    <SwitchPreference
-            android:key="priority"
-            android:title="@string/app_notification_priority_title"
-            android:summary="@string/app_notification_priority_summary"
-            android:order="2"
-            android:persistent="false" />
-
-    <!-- Sensitive -->
-    <SwitchPreference
-            android:key="sensitive"
-            android:title="@string/app_notification_sensitive_title"
-            android:summary="@string/app_notification_sensitive_summary"
-            android:order="4"
-            android:persistent="false" />
-
     <!-- App notification preferences -->
     <Preference
             android:key="app_settings"
diff --git a/res/xml/topic_notification_settings.xml b/res/xml/topic_notification_settings.xml
new file mode 100644
index 0000000..6826070
--- /dev/null
+++ b/res/xml/topic_notification_settings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/topic_notifications_title"
+        android:key="topic_notification_settings">
+
+    <!-- Bypass DND -->
+    <SwitchPreference
+            android:key="bypass_dnd"
+            android:title="@string/app_notification_override_dnd_title"
+            android:summary="@string/app_notification_override_dnd_summary"
+            android:order="2"
+            android:persistent="false" />
+
+    <!-- Sensitive -->
+    <SwitchPreference
+            android:key="sensitive"
+            android:title="@string/app_notification_sensitive_title"
+            android:summary="@string/app_notification_sensitive_summary"
+            android:order="4"
+            android:persistent="false" />
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/applications/AppStateNotificationBridge.java b/src/com/android/settings/applications/AppStateNotificationBridge.java
index 44a37a5..6d057b3 100644
--- a/src/com/android/settings/applications/AppStateNotificationBridge.java
+++ b/src/com/android/settings/applications/AppStateNotificationBridge.java
@@ -66,26 +66,4 @@
             return info.extraInfo != null && ((AppRow) info.extraInfo).banned;
         }
     };
-
-    public static final AppFilter FILTER_APP_NOTIFICATION_PRIORITY = new AppFilter() {
-        @Override
-        public void init() {
-        }
-
-        @Override
-        public boolean filterApp(AppEntry info) {
-            return info.extraInfo != null && ((AppRow) info.extraInfo).priority;
-        }
-    };
-
-    public static final AppFilter FILTER_APP_NOTIFICATION_SENSITIVE = new AppFilter() {
-        @Override
-        public void init() {
-        }
-
-        @Override
-        public boolean filterApp(AppEntry info) {
-            return info.extraInfo != null && ((AppRow) info.extraInfo).sensitive;
-        }
-    };
 }
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 4e8a168..32d3d2f 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -814,25 +814,7 @@
         if (appRow.banned) {
             return context.getString(R.string.notifications_disabled);
         }
-        ArrayList<CharSequence> notifSummary = new ArrayList<>();
-        if (appRow.priority) {
-            notifSummary.add(context.getString(R.string.notifications_priority));
-        }
-        if (appRow.sensitive) {
-            notifSummary.add(context.getString(R.string.notifications_sensitive));
-        }
-        switch (notifSummary.size()) {
-            case 3:
-                return context.getString(R.string.notifications_three_items,
-                        notifSummary.get(0), notifSummary.get(1), notifSummary.get(2));
-            case 2:
-                return context.getString(R.string.notifications_two_items,
-                        notifSummary.get(0), notifSummary.get(1));
-            case 1:
-                return notifSummary.get(0);
-            default:
-                return context.getString(R.string.notifications_enabled);
-        }
+        return context.getString(R.string.notifications_enabled);
     }
 
     private class MemoryUpdater extends AsyncTask<Void, Void, ProcStatsPackageEntry> {
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 384fbf8..bd1f28c 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -138,8 +138,6 @@
             R.string.filter_enabled_apps,  // Enabled
             R.string.filter_apps_disabled, // Disabled
             R.string.filter_notif_blocked_apps,   // Blocked Notifications
-            R.string.filter_notif_priority_apps,  // Priority Notifications
-            R.string.filter_notif_sensitive_apps, // Sensitive Notifications
             R.string.filter_personal_apps, // Personal
             R.string.filter_work_apps,     // Work
             R.string.filter_with_domain_urls_apps,     // Domain URLs
@@ -158,8 +156,6 @@
             ApplicationsState.FILTER_ALL_ENABLED, // Enabled
             ApplicationsState.FILTER_DISABLED,    // Disabled
             AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED,   // Blocked Notifications
-            AppStateNotificationBridge.FILTER_APP_NOTIFICATION_PRIORITY,  // Priority Notifications
-            AppStateNotificationBridge.FILTER_APP_NOTIFICATION_SENSITIVE, // Sensitive Notifications
             ApplicationsState.FILTER_PERSONAL,    // Personal
             ApplicationsState.FILTER_WORK,        // Work
             ApplicationsState.FILTER_WITH_DOMAIN_URLS,   // Apps with Domain URLs
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 2669f2f..deba7d4 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -54,8 +54,6 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String KEY_BLOCK = "block";
-    private static final String KEY_PRIORITY = "priority";
-    private static final String KEY_SENSITIVE = "sensitive";
     private static final String KEY_APP_SETTINGS = "app_settings";
 
     private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
@@ -66,8 +64,6 @@
 
     private Context mContext;
     private SwitchPreference mBlock;
-    private SwitchPreference mPriority;
-    private SwitchPreference mSensitive;
     private AppRow mAppRow;
     private boolean mCreated;
     private boolean mIsSystemPackage;
@@ -130,8 +126,6 @@
 
         addPreferencesFromResource(R.xml.app_notification_settings);
         mBlock = (SwitchPreference) findPreference(KEY_BLOCK);
-        mPriority = (SwitchPreference) findPreference(KEY_PRIORITY);
-        mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
 
         mAppRow = mBackend.loadAppRow(pm, info.applicationInfo);
 
@@ -140,10 +134,29 @@
         rows.put(mAppRow.pkg, mAppRow);
         collectConfigActivities(getPackageManager(), rows);
 
+        // Add topics
+        List<Notification.Topic> topics = mBackend.getTopics(pkg, mUid);
+        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);
+
+            Intent topicIntent = Utils.onBuildStartFragmentIntent(getActivity(),
+                    TopicNotificationSettings.class.getName(),
+                    topicArgs, null, R.string.topic_notifications_title, null, false);
+            topicPreference.setIntent(topicIntent);
+            // Add preference to the settings menu.
+            getPreferenceScreen().addPreference(topicPreference);
+        }
+
         mBlock.setChecked(mAppRow.banned);
         updateDependents(mAppRow.banned);
-        mPriority.setChecked(mAppRow.priority);
-        mSensitive.setChecked(mAppRow.sensitive);
 
         mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
             @Override
@@ -160,22 +173,6 @@
             }
         });
 
-        mPriority.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean priority = (Boolean) newValue;
-                return mBackend.setHighPriority(pkg, mUid, priority);
-            }
-        });
-
-        mSensitive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean sensitive = (Boolean) newValue;
-                return mBackend.setSensitive(pkg, mUid, sensitive);
-            }
-        });
-
         if (mAppRow.settingsIntent != null) {
             findPreference(KEY_APP_SETTINGS).setOnPreferenceClickListener(
                     new OnPreferenceClickListener() {
@@ -200,15 +197,7 @@
     }
 
     private void updateDependents(boolean banned) {
-        final boolean lockscreenSecure = new LockPatternUtils(getActivity()).isSecure(
-                UserHandle.myUserId());
-        final boolean lockscreenNotificationsEnabled = getLockscreenNotificationsEnabled();
-        final boolean allowPrivate = getLockscreenAllowPrivateNotifications();
-
         setVisible(mBlock, !mIsSystemPackage);
-        setVisible(mPriority, mIsSystemPackage || !banned);
-        setVisible(mSensitive, mIsSystemPackage || !banned && lockscreenSecure
-                && lockscreenNotificationsEnabled && allowPrivate);
     }
 
     private void setVisible(Preference p, boolean visible) {
@@ -221,16 +210,6 @@
         }
     }
 
-    private boolean getLockscreenNotificationsEnabled() {
-        return Settings.Secure.getInt(getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
-    }
-
-    private boolean getLockscreenAllowPrivateNotifications() {
-        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();
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index e86fee0..dcebf8b 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -15,17 +15,22 @@
  */
 package com.android.settings.notification;
 
+import com.google.android.collect.Lists;
+
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.graphics.drawable.Drawable;
 import android.os.ServiceManager;
 import android.service.notification.NotificationListenerService;
 import android.util.Log;
 
+import java.util.List;
+
 public class NotificationBackend {
     private static final String TAG = "NotificationBackend";
 
@@ -44,8 +49,19 @@
         }
         row.icon = app.loadIcon(pm);
         row.banned = getNotificationsBanned(row.pkg, row.uid);
-        row.priority = getHighPriority(row.pkg, row.uid);
-        row.sensitive = getSensitive(row.pkg, row.uid);
+        return row;
+    }
+
+    public TopicRow loadTopicRow(PackageManager pm, ApplicationInfo app, Notification.Topic topic) {
+        final TopicRow row = new TopicRow();
+        row.pkg = app.packageName;
+        row.uid = app.uid;
+        row.label = topic.getLabel();
+        row.icon = app.loadIcon(pm);
+        row.topic = topic;
+        row.priority = getBypassZenMode(row.pkg, row.uid, row.topic);
+        row.sensitive = getSensitive(row.pkg, row.uid, row.topic);
+        row.banned = getNotificationsBanned(row.pkg, row.uid);
         return row;
     }
 
@@ -69,19 +85,20 @@
         }
     }
 
-    public boolean getHighPriority(String pkg, int uid) {
+    public boolean getBypassZenMode(String pkg, int uid, Notification.Topic topic) {
         try {
-            return sINM.getPackagePriority(pkg, uid) == Notification.PRIORITY_MAX;
+            return sINM.getTopicPriority(pkg, uid, topic) == Notification.PRIORITY_MAX;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
             return false;
         }
     }
 
-    public boolean setHighPriority(String pkg, int uid, boolean highPriority) {
+    public boolean setBypassZenMode(String pkg, int uid, Notification.Topic topic,
+            boolean bypassZen) {
         try {
-            sINM.setPackagePriority(pkg, uid,
-                    highPriority ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT);
+            sINM.setTopicPriority(pkg, uid, topic,
+                    bypassZen ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT);
             return true;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
@@ -89,18 +106,19 @@
         }
     }
 
-    public boolean getSensitive(String pkg, int uid) {
+    public boolean getSensitive(String pkg, int uid, Notification.Topic topic) {
         try {
-            return sINM.getPackageVisibilityOverride(pkg, uid) == Notification.VISIBILITY_PRIVATE;
+            return sINM.getTopicVisibilityOverride(pkg, uid, topic)
+                    == Notification.VISIBILITY_PRIVATE;
         } catch (Exception e) {
             Log.w(TAG, "Error calling NoMan", e);
             return false;
         }
     }
 
-    public boolean setSensitive(String pkg, int uid, boolean sensitive) {
+    public boolean setSensitive(String pkg, int uid, Notification.Topic topic, boolean sensitive) {
         try {
-            sINM.setPackageVisibilityOverride(pkg, uid,
+            sINM.setTopicVisibilityOverride(pkg, uid, topic,
                     sensitive ? Notification.VISIBILITY_PRIVATE
                             : NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
             return true;
@@ -110,6 +128,16 @@
         }
     }
 
+    public List<Notification.Topic> getTopics(String pkg, int uid) {
+        try {
+            final ParceledListSlice<Notification.Topic> parceledList = sINM.getTopics(pkg, uid);
+            return parceledList.getList();
+        } catch (Exception e) {
+            Log.w(TAG, "Error calling NoMan", e);
+            return Lists.newArrayList();
+        }
+    }
+
     static class Row {
         public String section;
     }
@@ -121,9 +149,13 @@
         public CharSequence label;
         public Intent settingsIntent;
         public boolean banned;
+        public boolean first;  // first app in section
+    }
+
+    public static class TopicRow extends AppRow {
+        public Notification.Topic topic;
         public boolean priority;
         public boolean sensitive;
-        public boolean first;  // first app in section
     }
 
 }
diff --git a/src/com/android/settings/notification/TopicNotificationSettings.java b/src/com/android/settings/notification/TopicNotificationSettings.java
new file mode 100644
index 0000000..48c611e
--- /dev/null
+++ b/src/com/android/settings/notification/TopicNotificationSettings.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 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.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.TopicRow;
+
+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.os.UserHandle;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+/** These settings are per topic, so should not be returned in global search results. */
+public class TopicNotificationSettings extends SettingsPreferenceFragment {
+    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 final NotificationBackend mBackend = new NotificationBackend();
+
+    private Context mContext;
+    private SwitchPreference mPriority;
+    private SwitchPreference mSensitive;
+    private TopicRow mTopicRow;
+    private boolean mCreated;
+    private boolean mIsSystemPackage;
+    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 (mTopicRow == null) return;
+        AppHeader.createAppHeader(
+                this, mTopicRow.icon, mTopicRow.label, mTopicRow.pkg, mTopicRow.uid);
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return MetricsLogger.NOTIFICATION_TOPIC_NOTIFICATION;
+    }
+
+    @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 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();
+        mIsSystemPackage = Utils.isSystemPackage(pm, info);
+
+        addPreferencesFromResource(R.xml.topic_notification_settings);
+        mPriority = (SwitchPreference) findPreference(KEY_BYPASS_DND);
+        mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
+
+        mTopicRow = mBackend.loadTopicRow(pm, info.applicationInfo, topic);
+
+        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.banned);
+
+    }
+
+    @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(boolean banned) {
+        final boolean lockscreenSecure = new LockPatternUtils(getActivity()).isSecure(
+                UserHandle.myUserId());
+        final boolean lockscreenNotificationsEnabled = getLockscreenNotificationsEnabled();
+        final boolean allowPrivate = getLockscreenAllowPrivateNotifications();
+
+        setVisible(mPriority, mIsSystemPackage || !banned);
+        setVisible(mSensitive, mIsSystemPackage || !banned && 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;
+    }
+
+    private boolean getLockscreenAllowPrivateNotifications() {
+        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();
+    }
+}