diff --git a/res/values/strings.xml b/res/values/strings.xml index dcbf50de867..9048add6085 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6274,12 +6274,21 @@ Loading apps... + + Channels + Block all Never show notifications from this app + + Block all + + + Never show notifications from this channel + Override Do Not Disturb @@ -6304,6 +6313,12 @@ Importance + + Always pulse notification light + + + Always vibrate + Rule name diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml index ee9237c5543..2b2fc318d2b 100644 --- a/res/xml/app_notification_settings.xml +++ b/res/xml/app_notification_settings.xml @@ -55,4 +55,9 @@ android:order="6" settings:useAdditionalSummary="true" /> + + diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml new file mode 100644 index 00000000000..de0b9c7b2bf --- /dev/null +++ b/res/xml/channel_notification_settings.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java index 9feee13af93..6893a21801c 100644 --- a/src/com/android/settings/DefaultRingtonePreference.java +++ b/src/com/android/settings/DefaultRingtonePreference.java @@ -31,7 +31,7 @@ public class DefaultRingtonePreference extends RingtonePreference { private static final String TAG = "DefaultRingtonePreference"; private int mUserId; - private Context mUserContext; + protected Context mUserContext; public DefaultRingtonePreference(Context context, AttributeSet attrs) { super(context, attrs); diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java index 2b8daeb9ba3..c09557f1d4e 100644 --- a/src/com/android/settings/notification/AppNotificationSettings.java +++ b/src/com/android/settings/notification/AppNotificationSettings.java @@ -17,23 +17,24 @@ package com.android.settings.notification; import android.app.Notification; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; -import android.content.pm.UserInfo; import android.os.Bundle; -import android.os.UserHandle; -import android.service.notification.NotificationListenerService.Ranking; +import android.support.v7.preference.PreferenceCategory; import android.util.ArrayMap; import android.util.Log; import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.internal.widget.LockPatternUtils; import com.android.settings.AppHeader; import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.applications.AppInfoBase; import com.android.settings.notification.NotificationBackend.AppRow; +import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedSwitchPreference; @@ -48,8 +49,9 @@ public class AppNotificationSettings extends NotificationSettingsBase { = new Intent(Intent.ACTION_MAIN) .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES); - private AppRow mAppRow; - private boolean mDndVisualEffectsSuppressed; + private static final String KEY_CHANNELS = "channels"; + private PreferenceCategory mChannels; + List mChannelList; @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -77,51 +79,52 @@ public class AppNotificationSettings extends NotificationSettingsBase { KEY_VISIBILITY_OVERRIDE); mBlock = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BLOCK); mSilent = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_SILENT); + mChannels = (PreferenceCategory) findPreference(KEY_CHANNELS); if (mPkgInfo != null) { - mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); - - NotificationManager.Policy policy = - NotificationManager.from(mContext).getNotificationPolicy(); - mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0; - // load settings intent ArrayMap rows = new ArrayMap(); rows.put(mAppRow.pkg, mAppRow); collectConfigActivities(rows); + mChannelList = mBackend.getChannels(mPkg, mUid).getList(); - setupImportancePrefs(mAppRow.systemApp, mAppRow.appImportance, mAppRow.banned); + setupImportancePrefs(mAppRow.systemApp, mAppRow.appImportance, mAppRow.banned, + NotificationManager.IMPORTANCE_MAX); setupPriorityPref(mAppRow.appBypassDnd); setupVisOverridePref(mAppRow.appVisOverride); + + if (mChannelList.isEmpty()) { + setVisible(mChannels, false); + } else { + int N = mChannelList.size(); + for (int i = 0; i < N; i++) { + final NotificationChannel channel = mChannelList.get(i); + RestrictedPreference channelPref = new RestrictedPreference(getPrefContext()); + channelPref.setDisabledByAdmin(mSuspendedAppsAdmin); + channelPref.setKey(channel.getId()); + channelPref.setTitle(channel.getName()); + Bundle channelArgs = new Bundle(); + channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid); + channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true); + channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg); + channelArgs.putString(ARG_CHANNEL, channel.getId()); + + Intent topicIntent = Utils.onBuildStartFragmentIntent(getActivity(), + ChannelNotificationSettings.class.getName(), + channelArgs, null, 0, null, false); + channelPref.setIntent(topicIntent); + mChannels.addPreference(channelPref); + } + } updateDependents(mAppRow.appImportance); } } @Override protected void updateDependents(int importance) { - LockPatternUtils utils = new LockPatternUtils(getActivity()); - boolean lockscreenSecure = utils.isSecure(UserHandle.myUserId()); - UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId()); - if (parentUser != null){ - lockscreenSecure |= utils.isSecure(parentUser.id); - } - - if (getPreferenceScreen().findPreference(mBlock.getKey()) != null) { - setVisible(mSilent, checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance)); - mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW); - } - setVisible(mPriority, checkCanBeVisible(Ranking.IMPORTANCE_DEFAULT, importance) - || (checkCanBeVisible(Ranking.IMPORTANCE_LOW, importance) - && mDndVisualEffectsSuppressed)); - setVisible(mVisibilityOverride, - checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance) && lockscreenSecure); - } - - protected boolean checkCanBeVisible(int minImportanceVisible, int importance) { - if (importance == Ranking.IMPORTANCE_UNSPECIFIED) { - return true; - } - return importance >= minImportanceVisible; + super.updateDependents(importance); + setVisible(mChannels, + !(mChannelList.isEmpty() || importance == NotificationManager.IMPORTANCE_NONE)); } private List queryNotificationConfigActivities() { diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java new file mode 100644 index 00000000000..d3235456a2a --- /dev/null +++ b/src/com/android/settings/notification/ChannelNotificationSettings.java @@ -0,0 +1,197 @@ +/* + * 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.internal.logging.MetricsProto.MetricsEvent; +import com.android.settings.AppHeader; +import com.android.settings.R; +import com.android.settings.RingtonePreference; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedSwitchPreference; + +import android.app.NotificationManager; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.provider.Settings; +import android.service.notification.NotificationListenerService.Ranking; +import android.support.v7.preference.Preference; + +public class ChannelNotificationSettings extends NotificationSettingsBase { + protected static final String KEY_LIGHTS = "lights"; + protected static final String KEY_VIBRATE = "vibrate"; + protected static final String KEY_RINGTONE = "ringtone"; + + protected RestrictedSwitchPreference mLights; + protected RestrictedSwitchPreference mVibrate; + protected DefaultNotificationTonePreference mRingtone; + private int mMaxImportance; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (mAppRow == null || mChannel == null) return; + AppHeader.createAppHeader( + this, mAppRow.icon, mChannel.getName(), mAppRow.pkg, mAppRow.uid); + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.channel_notification_settings); + + mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE); + mPriority = + (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND); + mVisibilityOverride = + (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE); + mBlock = (RestrictedSwitchPreference) findPreference(KEY_BLOCK); + mSilent = (RestrictedSwitchPreference) findPreference(KEY_SILENT); + mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS); + mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE); + mRingtone = (DefaultNotificationTonePreference) findPreference(KEY_RINGTONE); + + if (mPkgInfo != null) { + setupPriorityPref(mChannel.canBypassDnd()); + if (mAppRow.appBypassDnd) { + mPriority.setShouldDisableView(true); + } + setupVisOverridePref(mChannel.getLockscreenVisibility()); + if (mAppRow.appVisOverride != Ranking.VISIBILITY_NO_OVERRIDE) { + mVisibilityOverride.setShouldDisableView(true); + } + setupLights(); + setupVibrate(); + setupRingtone(); + mMaxImportance = mAppRow.appImportance == NotificationManager.IMPORTANCE_UNSPECIFIED + ? NotificationManager.IMPORTANCE_MAX : mAppRow.appImportance; + setupImportancePrefs(false, mChannel.getImportance(), + mChannel.getImportance() == NotificationManager.IMPORTANCE_NONE, + mMaxImportance); + } + } + + @Override + public void onResume() { + super.onResume(); + if ((mUid != -1 && getPackageManager().getPackagesForUid(mUid) == null)) { + // App isn't around anymore, must have been removed. + finish(); + return; + } + mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended( + mContext, mPkg, mUserId); + if (mLights != null) { + mLights.setDisabledByAdmin(mSuspendedAppsAdmin); + } + if (mVibrate != null) { + mVibrate.setDisabledByAdmin(mSuspendedAppsAdmin); + } + } + + private void setupLights() { + mLights.setDisabledByAdmin(mSuspendedAppsAdmin); + mLights.setChecked(mChannel.shouldShowLights()); + mLights.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean lights = (Boolean) newValue; + mChannel.setLights(lights); + mBackend.updateChannel(mPkg, mUid, mChannel); + return true; + } + }); + } + + private void setupVibrate() { + mVibrate.setDisabledByAdmin(mSuspendedAppsAdmin); + mVibrate.setChecked(mChannel.shouldVibrate()); + mVibrate.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean vibrate = (Boolean) newValue; + mChannel.setVibration(vibrate); + mBackend.updateChannel(mPkg, mUid, mChannel); + return true; + } + }); + } + + private void setupRingtone() { + mRingtone.setRingtone(mChannel.getDefaultRingtone()); + mRingtone.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Uri ringtone = Uri.parse((String) newValue); + mRingtone.setRingtone(ringtone); + mChannel.setDefaultRingtone(ringtone); + mBackend.updateChannel(mPkg, mUid, mChannel); + return false; + } + }); + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) { + if (preference instanceof RingtonePreference) { + mRingtone.onPrepareRingtonePickerIntent(mRingtone.getIntent()); + startActivityForResult(preference.getIntent(), 200); + return true; + } + return super.onPreferenceTreeClick(preference); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (mRingtone != null) { + mRingtone.onActivityResult(requestCode, resultCode, data); + } + } + + private boolean canPulseLight() { + if (!getResources() + .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) { + return false; + } + return Settings.System.getInt(getContentResolver(), + Settings.System.NOTIFICATION_LIGHT_PULSE, 0) == 1; + } + + @Override + protected void updateDependents(int importance) { + if (importance == NotificationManager.IMPORTANCE_UNSPECIFIED) { + importance = mMaxImportance; + } + importance = Math.min(mMaxImportance, importance); + + super.updateDependents(importance); + setVisible(mLights, checkCanBeVisible( + NotificationManager.IMPORTANCE_LOW, importance) && canPulseLight()); + setVisible(mVibrate, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT, importance)); + setVisible(mRingtone, checkCanBeVisible( + NotificationManager.IMPORTANCE_DEFAULT, importance)); + if (mMaxImportance == NotificationManager.IMPORTANCE_LOW + && getPreferenceScreen().findPreference(mBlock.getKey()) != null) { + setVisible(mSilent, false); + } + } +} diff --git a/src/com/android/settings/notification/DefaultNotificationTonePreference.java b/src/com/android/settings/notification/DefaultNotificationTonePreference.java new file mode 100644 index 00000000000..3a7d3b1922a --- /dev/null +++ b/src/com/android/settings/notification/DefaultNotificationTonePreference.java @@ -0,0 +1,79 @@ +/* + * 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.DefaultRingtonePreference; +import com.android.settings.Utils; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.os.AsyncTask; +import android.os.UserHandle; +import android.os.UserManager; +import android.net.Uri; +import android.provider.MediaStore; +import android.provider.OpenableColumns; +import android.util.AttributeSet; + +import static android.content.ContentProvider.getUriWithoutUserId; + +public class DefaultNotificationTonePreference extends DefaultRingtonePreference { + private Uri mRingtone; + + public DefaultNotificationTonePreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected Uri onRestoreRingtone() { + return mRingtone; + } + + @Override + public void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) { + super.onPrepareRingtonePickerIntent(ringtonePickerIntent); + ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, + mRingtone); + } + + public void setRingtone(Uri ringtone) { + mRingtone = ringtone; + updateRingtoneName(mRingtone); + } + + private void updateRingtoneName(final Uri uri) { + AsyncTask ringtoneNameTask = new AsyncTask() { + @Override + protected CharSequence doInBackground(Object... params) { + return Ringtone.getTitle(mUserContext, uri, false /* followSettingsUri */, + true /* allowRemote */); + } + + @Override + protected void onPostExecute(CharSequence name) { + setSummary(name); + } + }; + ringtoneNameTask.execute(); + } +} \ No newline at end of file diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java index 1229b9e3cec..32eacc6b74e 100644 --- a/src/com/android/settings/notification/NotificationBackend.java +++ b/src/com/android/settings/notification/NotificationBackend.java @@ -17,11 +17,13 @@ package com.android.settings.notification; import android.app.INotificationManager; import android.app.Notification; +import android.app.NotificationChannel; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.graphics.drawable.Drawable; import android.os.ServiceManager; import android.os.UserHandle; @@ -141,6 +143,35 @@ public class NotificationBackend { } } + public NotificationChannel getChannel(String pkg, int uid, String channelId) { + if (channelId == null) { + return null; + } + try { + return sINM.getNotificationChannelForPackage(pkg, uid, channelId); + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return null; + } + } + + public ParceledListSlice getChannels(String pkg, int uid) { + try { + return sINM.getNotificationChannelsForPackage(pkg, uid); + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return ParceledListSlice.emptyList(); + } + } + + public void updateChannel(String pkg, int uid, NotificationChannel channel) { + try { + sINM.updateNotificationChannelForPackage(pkg, uid, channel); + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + } + } + static class Row { public String section; } @@ -159,4 +190,8 @@ public class NotificationBackend { public int appVisOverride; public boolean lockScreenSecure; } + + public static class ChannelRow extends AppRow { + public NotificationChannel channel; + } } diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java index 3469cc0a261..0925833a580 100644 --- a/src/com/android/settings/notification/NotificationSettingsBase.java +++ b/src/com/android/settings/notification/NotificationSettingsBase.java @@ -16,6 +16,7 @@ package com.android.settings.notification; +import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.applications.AppInfoBase; @@ -23,12 +24,15 @@ import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedSwitchPreference; import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; 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.content.pm.UserInfo; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; @@ -49,6 +53,8 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String TUNER_SETTING = "show_importance_slider"; + protected static final String ARG_CHANNEL = "channel"; + protected static final String KEY_BYPASS_DND = "bypass_dnd"; protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override"; protected static final String KEY_IMPORTANCE = "importance"; @@ -71,6 +77,10 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen protected RestrictedSwitchPreference mSilent; protected EnforcedAdmin mSuspendedAppsAdmin; protected boolean mShowSlider = false; + protected boolean mDndVisualEffectsSuppressed; + + protected NotificationChannel mChannel; + protected NotificationBackend.AppRow mAppRow; @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -122,9 +132,16 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen return; } + mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); + mChannel = (args != null && args.containsKey(ARG_CHANNEL)) ? + mBackend.getChannel(mPkg, mUid, args.getString(ARG_CHANNEL)) : null; + mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended( mContext, mPkg, mUserId); mShowSlider = Settings.Secure.getInt(getContentResolver(), TUNER_SETTING, 0) == 1; + NotificationManager.Policy policy = + NotificationManager.from(mContext).getNotificationPolicy(); + mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0; } @Override @@ -154,21 +171,27 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen } } - protected void setupImportancePrefs(boolean notBlockable, int importance, boolean banned) { + protected void setupImportancePrefs(boolean notBlockable, int importance, boolean banned, + int maxImportance) { if (mShowSlider) { setVisible(mBlock, false); setVisible(mSilent, false); mImportance.setDisabledByAdmin(mSuspendedAppsAdmin); mImportance.setMinimumProgress( notBlockable ? Ranking.IMPORTANCE_MIN : Ranking.IMPORTANCE_NONE); - mImportance.setMax(Ranking.IMPORTANCE_MAX); - mImportance.setProgress(importance); + mImportance.setMax(maxImportance); + mImportance.setProgress(Math.min(importance, maxImportance)); mImportance.setAutoOn(importance == Ranking.IMPORTANCE_UNSPECIFIED); mImportance.setCallback(new ImportanceSeekBarPreference.Callback() { @Override public void onImportanceChanged(int progress, boolean fromUser) { if (fromUser) { - mBackend.setImportance(mPkg, mUid, progress); + if (mChannel != null) { + mChannel.setImportance(progress); + mBackend.updateChannel(mPkg, mUid, mChannel); + } else { + mBackend.setImportance(mPkg, mUid, progress); + } } updateDependents(progress); } @@ -178,33 +201,56 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen if (notBlockable) { setVisible(mBlock, false); } else { - boolean blocked = importance == Ranking.IMPORTANCE_NONE || banned; - mBlock.setChecked(blocked); - mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean blocked = (Boolean) newValue; - final int importance = - blocked ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_UNSPECIFIED; - mBackend.setImportance(mPkgInfo.packageName, mUid, importance); - updateDependents(importance); - return true; - } - }); + mBlock.setChecked(banned); + mBlock.setOnPreferenceChangeListener( + new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, + Object newValue) { + final boolean blocked = (Boolean) newValue; + final int importance = blocked + ? Ranking.IMPORTANCE_NONE + : Ranking.IMPORTANCE_UNSPECIFIED; + if (mChannel != null) { + mChannel.setImportance(importance); + mBackend.updateChannel(mPkg, mUid, mChannel); + } else { + mBackend.setImportance(mPkgInfo.packageName, mUid, + importance); + } + updateDependents(importance); + return true; + } + }); + } + // app silenced; cannot un-silence a channel + if (maxImportance == NotificationManager.IMPORTANCE_LOW) { + setVisible(mSilent, false); + updateDependents(banned ? Ranking.IMPORTANCE_NONE : Ranking.IMPORTANCE_LOW); + } else { + mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW); + mSilent.setOnPreferenceChangeListener( + new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, + Object newValue) { + final boolean silenced = (Boolean) newValue; + final int importance = silenced + ? Ranking.IMPORTANCE_LOW + : Ranking.IMPORTANCE_UNSPECIFIED; + if (mChannel != null) { + mChannel.setImportance(importance); + mBackend.updateChannel(mPkg, mUid, mChannel); + } else { + mBackend.setImportance(mPkgInfo.packageName, mUid, + importance); + } + updateDependents(importance); + return true; + } + }); + updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance); } - mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW); - mSilent.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean silenced = (Boolean) newValue; - final int importance = - silenced ? Ranking.IMPORTANCE_LOW : Ranking.IMPORTANCE_UNSPECIFIED; - mBackend.setImportance(mPkgInfo.packageName, mUid, importance); - updateDependents(importance); - return true; - } - }); - updateDependents(banned ? Ranking.IMPORTANCE_NONE : importance); } } @@ -215,7 +261,13 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean bypassZenMode = (Boolean) newValue; - return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, bypassZenMode); + if (mChannel != null) { + mChannel.setBypassDnd(bypassZenMode); + mBackend.updateChannel(mPkg, mUid, mChannel); + return true; + } else { + return mBackend.setBypassZenMode(mPkgInfo.packageName, mUid, bypassZenMode); + } } }); } @@ -261,7 +313,12 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen if (sensitive == getGlobalVisibility()) { sensitive = Ranking.VISIBILITY_NO_OVERRIDE; } - mBackend.setVisibilityOverride(mPkgInfo.packageName, mUid, sensitive); + if (mChannel != null) { + mChannel.setLockscreenVisibility(sensitive); + mBackend.updateChannel(mPkg, mUid, mChannel); + } else { + mBackend.setVisibilityOverride(mPkgInfo.packageName, mUid, sensitive); + } return true; } }); @@ -287,17 +344,38 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen return globalVis; } - protected boolean getLockscreenNotificationsEnabled() { + private boolean getLockscreenNotificationsEnabled() { return Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0; } - protected boolean getLockscreenAllowPrivateNotifications() { + private boolean getLockscreenAllowPrivateNotifications() { return Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0; } - abstract void updateDependents(int progress); + private boolean isLockScreenSecure() { + LockPatternUtils utils = new LockPatternUtils(getActivity()); + boolean lockscreenSecure = utils.isSecure(UserHandle.myUserId()); + UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId()); + if (parentUser != null){ + lockscreenSecure |= utils.isSecure(parentUser.id); + } + + return lockscreenSecure; + } + + protected void updateDependents(int importance) { + if (getPreferenceScreen().findPreference(mBlock.getKey()) != null) { + setVisible(mSilent, checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance)); + mSilent.setChecked(importance == Ranking.IMPORTANCE_LOW); + } + setVisible(mPriority, checkCanBeVisible(Ranking.IMPORTANCE_DEFAULT, importance) + || (checkCanBeVisible(Ranking.IMPORTANCE_LOW, importance) + && mDndVisualEffectsSuppressed)); + setVisible(mVisibilityOverride, + checkCanBeVisible(Ranking.IMPORTANCE_MIN, importance) && isLockScreenSecure()); + } protected void setVisible(Preference p, boolean visible) { final boolean isVisible = getPreferenceScreen().findPreference(p.getKey()) != null; @@ -309,6 +387,13 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen } } + protected boolean checkCanBeVisible(int minImportanceVisible, int importance) { + if (importance == Ranking.IMPORTANCE_UNSPECIFIED) { + return true; + } + return importance >= minImportanceVisible; + } + protected void toastAndFinish() { Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show(); getActivity().finish();