diff --git a/res/values/strings.xml b/res/values/strings.xml
index db986f1659ec0d08d6d0fe879cb5bbd6f6e65a64..8614d7a11be6c7170051c53458c59ec4927eb16d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6011,6 +6011,9 @@
App notifications
+
+ Topic notifications
+
Other sounds
@@ -6093,17 +6096,17 @@
Never show notifications from this app
-
- Treat as priority
+
+ Override Do Not Disturb
-
- Let this app\u2019s notifications be heard when Do not disturb is set to Priority only
+
+ Let these notifications continue to interrupt when Do Not Disturb is set to Priority Only
Hide sensitive content
- When the device is locked, hide content in this app\u2019s notifications that might reveal private information
+ When the device is locked, hide content in these notifications that might reveal private information
Blocked
@@ -6484,10 +6487,6 @@
Normal
Block
-
- Sensitive content hidden
-
- Priority
%1$s / %2$s
@@ -6528,10 +6527,6 @@
Work
Blocked
-
- Priority
-
- Sensitive content hidden
With domain URLs
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index 149b9fc3933b546f0ee238bcfeda8bdf353106c4..6e27a075b383f96c0e0895175edbfe0a4db24183 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" />
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/applications/AppStateNotificationBridge.java b/src/com/android/settings/applications/AppStateNotificationBridge.java
index 44a37a5624ad18148a762ebdfeb047610bb9e036..6d057b35b65fa1b9f979ae4081a9cf39ffab779e 100644
--- a/src/com/android/settings/applications/AppStateNotificationBridge.java
+++ b/src/com/android/settings/applications/AppStateNotificationBridge.java
@@ -66,26 +66,4 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
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 4e8a168ad2c3a10c8f1afa2d1384fb2fb99a9d46..32d3d2ffb73a11971b0acbd5eb67219fe5181c38 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -814,25 +814,7 @@ public class InstalledAppDetails extends AppInfoBase
if (appRow.banned) {
return context.getString(R.string.notifications_disabled);
}
- ArrayList 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 {
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 384fbf80d5dc5d08dda01046001b92fd62b1a22c..bd1f28c4774ecac1eb6cc3b7598f92cb45beece1 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -138,8 +138,6 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 2669f2fcec07bc5fa9b6d68a573de6213757d696..deba7d41b243c7c28b95cccf2ad0f868c5d0835a 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -54,8 +54,6 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(getPackageManager(), rows);
+ // Add topics
+ List 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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
}
});
- 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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
}
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 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
}
}
- 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 e86fee012a0885a640e6911d3329648d9a9894fa..dcebf8b29cfd65be64b9658170316c42197fc17e 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 @@ public class NotificationBackend {
}
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 class NotificationBackend {
}
}
- 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 class NotificationBackend {
}
}
- 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 class NotificationBackend {
}
}
+ public List getTopics(String pkg, int uid) {
+ try {
+ final ParceledListSlice 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 class NotificationBackend {
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 0000000000000000000000000000000000000000..48c611e84c06b235634bf8e1dad5d68f204abf37
--- /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();
+ }
+}