diff --git a/res/layout/zen_custom_settings_dialog.xml b/res/layout/zen_custom_settings_dialog.xml
new file mode 100644
index 00000000000..f44b2f720d7
--- /dev/null
+++ b/res/layout/zen_custom_settings_dialog.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index f95809ea3d2..3ba1b0c95f9 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1081,14 +1081,14 @@
- @string/zen_mode_from_anyone
- @string/zen_mode_from_contacts
- @string/zen_mode_from_starred
- - @string/zen_mode_from_none_calls
+ - @string/zen_mode_from_none_messages
- @string/zen_mode_from_anyone
- @string/zen_mode_from_contacts
- @string/zen_mode_from_starred
- - @string/zen_mode_from_none_messages
+ - @string/zen_mode_from_none_calls
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1aaa374d617..3ba2c55c0b4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7328,8 +7328,8 @@
Do Not Disturb will stay on until you turn it off
-
- Do Not Disturb was automatically turned on by a rule (%s)
+
+ Do Not Disturb was automatically turned on by a schedule (%s)
Do Not Disturb was automatically turned on by an app (%s)
@@ -7337,6 +7337,9 @@
Do Not Disturb is on for %s with custom settings.
+
+ View custom settings
+
Priority only
@@ -7400,6 +7403,17 @@
Muted, but allow %1$s, %2$s, and %3$s
+
+ Custom settings
+
+ Review schedule
+
+ Got it
+
+ Notifications
+
+ Duration
+
Messages, events & reminders
@@ -7941,6 +7955,9 @@
Create custom settings for this schedule
+
+ For \u2018%1$s\u2019
+
,\u0020
@@ -7956,9 +7973,12 @@
Calls
-
+
When Do Not Disturb is on, incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
+ For \u2018%1$s\u2019 incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
Starred contacts
@@ -7974,6 +7994,9 @@
When Do Not Disturb is on, incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
+ For \u2018%1$s\u2019 incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
Text messages
@@ -8037,11 +8060,11 @@
App exceptions
-
+
- No apps can override Do Not Disturb
- - 1 app can override Do Not Disturb
- - %1$d apps can override Do Not Disturb
+ - Notifications from 1 app can override Do Not Disturb
+ - Notifications from %1$d apps can override Do Not Disturb
diff --git a/res/xml/zen_mode_custom_rule_configuration.xml b/res/xml/zen_mode_custom_rule_configuration.xml
new file mode 100644
index 00000000000..c1732a3ac6a
--- /dev/null
+++ b/res/xml/zen_mode_custom_rule_configuration.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/zen_mode_custom_rule_settings.xml b/res/xml/zen_mode_custom_rule_settings.xml
new file mode 100644
index 00000000000..7aedd2c5e01
--- /dev/null
+++ b/res/xml/zen_mode_custom_rule_settings.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/zen_mode_event_rule_settings.xml b/res/xml/zen_mode_event_rule_settings.xml
index a70b46ce30f..841fc065a85 100644
--- a/res/xml/zen_mode_event_rule_settings.xml
+++ b/res/xml/zen_mode_event_rule_settings.xml
@@ -45,4 +45,10 @@
android:title="@string/zen_mode_event_rule_reply"
android:summary="%s" />
+
+
+
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index 7de10b3cad9..84848541894 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -50,7 +50,7 @@
diff --git a/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java
new file mode 100644
index 00000000000..409eec62ece
--- /dev/null
+++ b/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.AutomaticZenRule;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+abstract class AbstractZenCustomRulePreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+
+ String mId;
+ AutomaticZenRule mRule;
+
+ AbstractZenCustomRulePreferenceController(Context context, String key,
+ Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (mId != null) {
+ mRule = mBackend.getAutomaticZenRule(mId);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mRule != null;
+ }
+
+ public void onResume(AutomaticZenRule rule, String id) {
+ mId = id;
+ mRule = rule;
+ }
+
+ Bundle createBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(ZenCustomRuleSettings.RULE_ID, mId);
+ return bundle;
+ }
+}
diff --git a/src/com/android/settings/notification/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
index 383934a236c..0e45e58c62d 100644
--- a/src/com/android/settings/notification/AbstractZenModePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
@@ -50,7 +50,7 @@ abstract public class AbstractZenModePreferenceController extends
@VisibleForTesting
protected SettingObserver mSettingObserver;
- private final String KEY;
+ final String KEY;
final private NotificationManager mNotificationManager;
protected static ZenModeConfigWrapper mZenModeConfigWrapper;
protected MetricsFeatureProvider mMetricsFeatureProvider;
diff --git a/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java b/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java
new file mode 100644
index 00000000000..3f75a20ff45
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleBlockedEffectsSettings extends ZenCustomRuleSettingsBase {
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ mFooterPreferenceMixin.createFooterPreference().setTitle(
+ R.string.zen_mode_blocked_effects_footer);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_block_settings;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_intent", ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_light", ZenPolicy.VISUAL_EFFECT_LIGHTS,
+ MetricsEvent.ACTION_ZEN_BLOCK_LIGHT, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_peek", ZenPolicy.VISUAL_EFFECT_PEEK,
+ MetricsEvent.ACTION_ZEN_BLOCK_PEEK, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_status", ZenPolicy.VISUAL_EFFECT_STATUS_BAR,
+ MetricsEvent.ACTION_ZEN_BLOCK_STATUS,
+ new int[] {ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST}));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_badge", ZenPolicy.VISUAL_EFFECT_BADGE,
+ MetricsEvent.ACTION_ZEN_BLOCK_BADGE, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_ambient", ZenPolicy.VISUAL_EFFECT_AMBIENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_AMBIENT, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_list", ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST,
+ MetricsEvent.ACTION_ZEN_BLOCK_NOTIFICATION_LIST, null));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return null;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_RULE_VIS_EFFECTS;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java b/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java
new file mode 100644
index 00000000000..808264e0ad5
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleCallsSettings extends ZenCustomRuleSettingsBase {
+ private static final String CALLS_KEY = "zen_mode_calls";
+ private static final String REPEAT_CALLERS_KEY = "zen_mode_repeat_callers";
+ private static final String STARRED_CONTACTS_KEY = "zen_mode_starred_contacts_callers";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_mode_settings_category_calls";
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return com.android.settings.R.xml.zen_mode_calls_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_CALLS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleCallsPreferenceController(context, CALLS_KEY,
+ getSettingsLifecycle()));
+ mControllers.add(new ZenRuleRepeatCallersPreferenceController(context,
+ REPEAT_CALLERS_KEY, getSettingsLifecycle(), context.getResources()
+ .getInteger(com.android.internal.R.integer.config_zen_repeat_callers_threshold)));
+ mControllers.add(new ZenRuleStarredContactsPreferenceController(context,
+ getSettingsLifecycle(), ZenPolicy.PRIORITY_CATEGORY_CALLS, STARRED_CONTACTS_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void updatePreferences() {
+ super.updatePreferences();
+ PreferenceScreen screen = getPreferenceScreen();
+ Preference footerPreference = screen.findPreference(FooterPreference.KEY_FOOTER);
+ footerPreference.setTitle(mContext.getResources().getString(
+ R.string.zen_mode_custom_calls_footer, mRule.getName()));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java b/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java
new file mode 100644
index 00000000000..fd8ce2be2e1
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleConfigSettings extends ZenCustomRuleSettingsBase {
+ private static final String CALLS_KEY = "zen_rule_calls_settings";
+ private static final String MESSAGES_KEY = "zen_rule_messages_settings";
+ private static final String ALARMS_KEY = "zen_rule_alarms";
+ private static final String MEDIA_KEY = "zen_rule_media";
+ private static final String SYSTEM_KEY = "zen_rule_system";
+ private static final String REMINDERS_KEY = "zen_rule_reminders";
+ private static final String EVENTS_KEY = "zen_rule_events";
+ private static final String NOTIFICATIONS_KEY = "zen_rule_notifications";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_custom_rule_configuration_category";
+
+ private Preference mCallsPreference;
+ private Preference mMessagesPreference;
+ private Preference mNotificationsPreference;
+ private ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(mContext);
+
+ mCallsPreference = getPreferenceScreen().findPreference(CALLS_KEY);
+ mCallsPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleCallsSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_CALLS)
+ .launch();
+ return true;
+ }
+ });
+
+ mMessagesPreference = getPreferenceScreen().findPreference(MESSAGES_KEY);
+ mMessagesPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleMessagesSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_MESSAGES)
+ .launch();
+ return true;
+ }
+ });
+
+ mNotificationsPreference = getPreferenceScreen().findPreference(NOTIFICATIONS_KEY);
+ mNotificationsPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleNotificationsSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory
+ (MetricsEvent.ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS)
+ .launch();
+ return true;
+ }
+ });
+
+ updateSummaries();
+ }
+
+ @Override
+ public void onZenModeConfigChanged() {
+ super.onZenModeConfigChanged();
+ updateSummaries();
+ }
+
+ /**
+ * Updates summaries of preferences without preference controllers
+ */
+ private void updateSummaries() {
+ NotificationManager.Policy noManPolicy = mBackend.toNotificationPolicy(
+ mRule.getZenPolicy());
+
+ mCallsPreference.setSummary(mSummaryBuilder.getCallsSettingSummary(noManPolicy));
+ mMessagesPreference.setSummary(mSummaryBuilder.getMessagesSettingSummary(noManPolicy));
+ mNotificationsPreference.setSummary(mSummaryBuilder.getBlockedEffectsSummary(noManPolicy));
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_custom_rule_configuration;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_RULE_SOUND_SETTINGS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), ALARMS_KEY, ZenPolicy.PRIORITY_CATEGORY_ALARMS,
+ MetricsEvent.ACTION_ZEN_ALLOW_ALARMS));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), MEDIA_KEY, ZenPolicy.PRIORITY_CATEGORY_MEDIA,
+ MetricsEvent.ACTION_ZEN_ALLOW_MEDIA));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), SYSTEM_KEY, ZenPolicy.PRIORITY_CATEGORY_SYSTEM,
+ MetricsEvent.ACTION_ZEN_ALLOW_SYSTEM));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), REMINDERS_KEY, ZenPolicy.PRIORITY_CATEGORY_REMINDERS,
+ MetricsEvent.ACTION_ZEN_ALLOW_REMINDERS));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), EVENTS_KEY, ZenPolicy.PRIORITY_CATEGORY_EVENTS,
+ MetricsEvent.ACTION_ZEN_ALLOW_EVENTS));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateSummaries();
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java b/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java
new file mode 100644
index 00000000000..8db2824efaf
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleMessagesSettings extends ZenCustomRuleSettingsBase {
+ private static final String MESSAGES_KEY = "zen_mode_messages";
+ private static final String STARRED_CONTACTS_KEY = "zen_mode_starred_contacts_messages";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_mode_settings_category_messages";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return com.android.settings.R.xml.zen_mode_messages_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_MESSAGES;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleMessagesPreferenceController(context, MESSAGES_KEY,
+ getSettingsLifecycle()));
+ mControllers.add(new ZenRuleStarredContactsPreferenceController(context,
+ getSettingsLifecycle(), ZenPolicy.PRIORITY_CATEGORY_MESSAGES,
+ STARRED_CONTACTS_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void updatePreferences() {
+ super.updatePreferences();
+ PreferenceScreen screen = getPreferenceScreen();
+ Preference footerPreference = screen.findPreference(FooterPreference.KEY_FOOTER);
+ footerPreference.setTitle(mContext.getResources().getString(
+ R.string.zen_mode_custom_messages_footer, mRule.getName()));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java b/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java
new file mode 100644
index 00000000000..a23bc6dd7c7
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleNotificationsSettings extends ZenCustomRuleSettingsBase {
+ private static final String VIS_EFFECTS_ALL_KEY = "zen_mute_notifications";
+ private static final String VIS_EFFECTS_NONE_KEY = "zen_hide_notifications";
+ private static final String VIS_EFFECTS_CUSTOM_KEY = "zen_custom";
+ private static final String PREFERENCE_CATEGORY_KEY = "restrict_category";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_restrict_notifications_settings;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleVisEffectsAllPreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_ALL_KEY));
+ mControllers.add(new ZenRuleVisEffectsNonePreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_NONE_KEY));
+ mControllers.add(new ZenRuleVisEffectsCustomPreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_CUSTOM_KEY));
+ mControllers.add(new ZenRuleNotifFooterPreferenceController(context, getSettingsLifecycle(),
+ FooterPreference.KEY_FOOTER));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleSettings.java b/src/com/android/settings/notification/ZenCustomRuleSettings.java
new file mode 100644
index 00000000000..ebd63064ccd
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleSettings.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleSettings extends ZenCustomRuleSettingsBase {
+ private static final String RULE_DEFAULT_POLICY_KEY = "zen_custom_rule_setting_default";
+ private static final String CUSTOM_RULE_POLICY_KEY = "zen_custom_rule_setting";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_custom_rule_category";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_custom_rule_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_SETTINGS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleDefaultPolicyPreferenceController(
+ context, getSettingsLifecycle(), RULE_DEFAULT_POLICY_KEY));
+ mControllers.add(new ZenRuleCustomPolicyPreferenceController(
+ context, getSettingsLifecycle(), CUSTOM_RULE_POLICY_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java b/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java
new file mode 100644
index 00000000000..94b0b7b9903
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.AutomaticZenRule;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class ZenCustomRuleSettingsBase extends ZenModeSettingsBase {
+ static final String TAG = "ZenCustomRuleSettings";
+ static final String RULE_ID = "RULE_ID";
+
+ String mId;
+ AutomaticZenRule mRule;
+ List mControllers = new ArrayList<>();
+
+ /**
+ * @return null if no preference category exists
+ */
+ abstract String getPreferenceCategoryKey();
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ Bundle bundle = getArguments();
+ if (bundle != null && bundle.containsKey(RULE_ID)) {
+ mId = bundle.getString(RULE_ID);
+ mRule = mBackend.getAutomaticZenRule(mId);
+ } else {
+ Log.d(TAG, "Rule id required to set custom dnd rule config settings");
+ this.finish();
+ }
+ }
+
+ @Override
+ public void onZenModeConfigChanged() {
+ super.onZenModeConfigChanged();
+ updatePreferences();
+ }
+
+ public void updatePreferences() {
+ mRule = mBackend.getAutomaticZenRule(mId);
+ final PreferenceScreen screen = getPreferenceScreen();
+ String categoryKey = getPreferenceCategoryKey();
+ if (categoryKey != null) {
+ Preference prefCategory = screen.findPreference(categoryKey);
+ if (prefCategory != null) {
+ prefCategory.setTitle(mContext.getResources().getString(
+ com.android.settings.R.string.zen_mode_custom_behavior_category_title,
+ mRule.getName()));
+ }
+ }
+
+ for (AbstractPreferenceController controller : mControllers) {
+ AbstractZenCustomRulePreferenceController zenRuleController =
+ (AbstractZenCustomRulePreferenceController) controller;
+ zenRuleController.onResume(mRule, mId);
+ zenRuleController.displayPreference(screen);
+ updatePreference(zenRuleController);
+ }
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_uri_interruptions;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updatePreferences();
+ }
+
+ Bundle createZenRuleBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(RULE_ID, mId);
+ return bundle;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index a75f51c423d..4c9cebe8451 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -23,15 +23,20 @@ import android.app.ActivityManager;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
+import android.database.Cursor;
+import android.icu.text.ListFormatter;
import android.net.Uri;
+import android.provider.ContactsContract;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenPolicy;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -116,7 +121,7 @@ public class ZenModeBackend {
return (mPolicy.priorityCategories & categoryType) != 0;
}
- protected int getNewPriorityCategories(boolean allow, int categoryType) {
+ protected int getNewDefaultPriorityCategories(boolean allow, int categoryType) {
int priorityCategories = mPolicy.priorityCategories;
if (allow) {
priorityCategories |= categoryType;
@@ -135,7 +140,8 @@ public class ZenModeBackend {
}
protected int getPriorityMessageSenders() {
- if (isPriorityCategoryEnabled(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)) {
+ if (isPriorityCategoryEnabled(
+ NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)) {
return mPolicy.priorityMessageSenders;
}
return SOURCE_NONE;
@@ -151,7 +157,7 @@ public class ZenModeBackend {
}
protected void saveSoundPolicy(int category, boolean allow) {
- int priorityCategories = getNewPriorityCategories(allow, category);
+ int priorityCategories = getNewDefaultPriorityCategories(allow, category);
savePolicy(priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, mPolicy.suppressedVisualEffects);
}
@@ -163,6 +169,7 @@ public class ZenModeBackend {
mNotificationManager.setNotificationPolicy(mPolicy);
}
+
private int getNewSuppressedEffects(boolean suppress, int effectType) {
int effects = mPolicy.suppressedVisualEffects;
@@ -202,7 +209,7 @@ public class ZenModeBackend {
priorityMessagesSenders = allowSendersFrom;
}
- savePolicy(getNewPriorityCategories(allowSenders, category),
+ savePolicy(getNewDefaultPriorityCategories(allowSenders, category),
priorityCallSenders, priorityMessagesSenders, mPolicy.suppressedVisualEffects);
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allow" +
@@ -236,6 +243,20 @@ public class ZenModeBackend {
return categorySenders;
}
+ protected static String getKeyFromZenPolicySetting(int contactType) {
+ switch (contactType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return ZEN_MODE_FROM_ANYONE;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return ZEN_MODE_FROM_CONTACTS;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return ZEN_MODE_FROM_STARRED;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return ZEN_MODE_FROM_NONE;
+ }
+ }
+
protected static String getKeyFromSetting(int contactType) {
switch (contactType) {
case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
@@ -288,6 +309,50 @@ public class ZenModeBackend {
}
}
+ protected int getContactsCallsSummary(ZenPolicy policy) {
+ int peopleType = policy.getPriorityCallSenders();
+ switch (peopleType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return R.string.zen_mode_from_anyone;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return R.string.zen_mode_from_contacts;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return R.string.zen_mode_from_starred;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return R.string.zen_mode_from_none_calls;
+ }
+ }
+
+ protected int getContactsMessagesSummary(ZenPolicy policy) {
+ int peopleType = policy.getPriorityMessageSenders();
+ switch (peopleType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return R.string.zen_mode_from_anyone;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return R.string.zen_mode_from_contacts;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return R.string.zen_mode_from_starred;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return R.string.zen_mode_from_none_messages;
+ }
+ }
+
+ protected static int getZenPolicySettingFromPrefKey(String key) {
+ switch (key) {
+ case ZEN_MODE_FROM_ANYONE:
+ return ZenPolicy.PEOPLE_TYPE_ANYONE;
+ case ZEN_MODE_FROM_CONTACTS:
+ return ZenPolicy.PEOPLE_TYPE_CONTACTS;
+ case ZEN_MODE_FROM_STARRED:
+ return ZenPolicy.PEOPLE_TYPE_STARRED;
+ case ZEN_MODE_FROM_NONE:
+ default:
+ return ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+ }
+
protected static int getSettingFromPrefKey(String key) {
switch (key) {
case ZEN_MODE_FROM_ANYONE:
@@ -318,6 +383,40 @@ public class ZenModeBackend {
}
}
+ ZenPolicy setDefaultZenPolicy(ZenPolicy zenPolicy) {
+ int calls;
+ if (mPolicy.allowCalls()) {
+ calls = ZenModeConfig.getZenPolicySenders(mPolicy.allowCallsFrom());
+ } else {
+ calls = ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+
+ int messages;
+ if (mPolicy.allowMessages()) {
+ messages = ZenModeConfig.getZenPolicySenders(mPolicy.allowMessagesFrom());
+ } else {
+ messages = ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+
+ return new ZenPolicy.Builder(zenPolicy)
+ .allowAlarms(mPolicy.allowAlarms())
+ .allowCalls(calls)
+ .allowEvents(mPolicy.allowEvents())
+ .allowMedia(mPolicy.allowMedia())
+ .allowMessages(messages)
+ .allowReminders(mPolicy.allowReminders())
+ .allowRepeatCallers(mPolicy.allowRepeatCallers())
+ .allowSystem(mPolicy.allowSystem())
+ .showFullScreenIntent(mPolicy.showFullScreenIntents())
+ .showLights(mPolicy.showLights())
+ .showInAmbientDisplay(mPolicy.showAmbient())
+ .showInNotificationList(mPolicy.showInNotificationList())
+ .showBadges(mPolicy.showBadges())
+ .showPeeking(mPolicy.showPeeking())
+ .showStatusBarIcons(mPolicy.showStatusBarIcons())
+ .build();
+ }
+
protected Map.Entry[] getAutomaticZenRules() {
Map ruleMap =
NotificationManager.from(mContext).getAutomaticZenRules();
@@ -338,6 +437,70 @@ public class ZenModeBackend {
return mDefaultRuleIds;
}
+ NotificationManager.Policy toNotificationPolicy(ZenPolicy policy) {
+ ZenModeConfig config = new ZenModeConfig();
+ return config.toNotificationPolicy(policy);
+ }
+
+ @VisibleForTesting
+ List getStarredContacts(Cursor cursor) {
+ List starredContacts = new ArrayList<>();
+ if (cursor != null && cursor.moveToFirst()) {
+ do {
+ String contact = cursor.getString(0);
+ if (contact != null) {
+ starredContacts.add(contact);
+ }
+ } while (cursor.moveToNext());
+ }
+ return starredContacts;
+ }
+
+ private List getStarredContacts() {
+ Cursor cursor = null;
+ try {
+ cursor = queryData();
+ return getStarredContacts(cursor);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ public String getStarredContactsSummary() {
+ List starredContacts = getStarredContacts();
+ int numStarredContacts = starredContacts.size();
+
+ List displayContacts = new ArrayList<>();
+
+ if (numStarredContacts == 0) {
+ displayContacts.add(mContext.getString(R.string.zen_mode_from_none));
+ } else {
+ for (int i = 0; i < 2 && i < numStarredContacts; i++) {
+ displayContacts.add(starredContacts.get(i));
+ }
+
+ if (numStarredContacts == 3) {
+ displayContacts.add(starredContacts.get(2));
+ } else if (numStarredContacts > 2) {
+ displayContacts.add(mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_starred_contacts_summary_additional_contacts,
+ numStarredContacts - 2, numStarredContacts - 2));
+ }
+ }
+
+ // values in displayContacts must not be null
+ return ListFormatter.getInstance().format(displayContacts);
+ }
+
+ private Cursor queryData() {
+ return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
+ new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
+ ContactsContract.Data.STARRED + "=1", null,
+ ContactsContract.Data.TIMES_CONTACTED);
+ }
+
@VisibleForTesting
public static final Comparator> RULE_COMPARATOR =
new Comparator>() {
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index e573884181a..46162a8f170 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -30,13 +30,15 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.SubSettingLauncher;
public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected static final String TAG = ZenModeSettingsBase.TAG;
protected static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
+ private final String CUSTOM_BEHAVIOR_KEY = "zen_custom_setting";
+
protected Context mContext;
protected boolean mDisableListeners;
protected AutomaticZenRule mRule;
@@ -45,6 +47,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected ZenAutomaticRuleHeaderPreferenceController mHeader;
protected ZenRuleButtonsPreferenceController mActionButtons;
protected ZenAutomaticRuleSwitchPreferenceController mSwitch;
+ protected Preference mCustomBehaviorPreference;
abstract protected void onCreateInternal();
abstract protected boolean setRule(AutomaticZenRule rule);
@@ -75,6 +78,21 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
}
super.onCreate(icicle);
+ mCustomBehaviorPreference = getPreferenceScreen().findPreference(CUSTOM_BEHAVIOR_KEY);
+ mCustomBehaviorPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Bundle bundle = new Bundle();
+ bundle.putString(ZenCustomRuleSettings.RULE_ID, mId);
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleSettings.class.getName())
+ .setArguments(bundle)
+ .setSourceMetricsCategory(0) // TODO
+ .launch();
+ return true;
+ }
+ });
onCreateInternal();
}
@@ -84,7 +102,9 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
if (isUiRestricted()) {
return;
}
- updateControls();
+ if (!refreshRuleOrFinish()) {
+ updateControls();
+ }
}
@Override
@@ -111,22 +131,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
updatePreference(mActionButtons);
}
- private void updatePreference(AbstractPreferenceController controller) {
- final PreferenceScreen screen = getPreferenceScreen();
- if (!controller.isAvailable()) {
- return;
- }
- final String key = controller.getPreferenceKey();
-
- final Preference preference = screen.findPreference(key);
- if (preference == null) {
- Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
- key, controller.getClass().getSimpleName()));
- return;
- }
- controller.updateState(preference);
- }
-
protected void updateRule(Uri newConditionId) {
mRule.setConditionId(newConditionId);
mBackend.updateZenRule(mId, mRule);
@@ -165,6 +169,11 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
mDisableListeners = true;
updateControlsInternal();
updateHeader();
+ if (mRule.getZenPolicy() == null) {
+ mCustomBehaviorPreference.setSummary(R.string.zen_mode_custom_behavior_summary_default);
+ } else {
+ mCustomBehaviorPreference.setSummary(R.string.zen_mode_custom_behavior_summary);
+ }
mDisableListeners = false;
}
}
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index a3f59c680d5..bdf80a6180a 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -90,7 +90,8 @@ public class ZenModeSettings extends ZenModeSettingsBase {
controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
- controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
+ fragmentManager));
return controllers;
}
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index b9a14eec1ce..3f538794836 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -26,7 +26,11 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Log;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
protected static final String TAG = "ZenModeSettings";
@@ -121,4 +125,20 @@ abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
}
}
}
+
+ void updatePreference(AbstractPreferenceController controller) {
+ final PreferenceScreen screen = getPreferenceScreen();
+ if (!controller.isAvailable()) {
+ return;
+ }
+ final String key = controller.getPreferenceKey();
+
+ final Preference preference = screen.findPreference(key);
+ if (preference == null) {
+ Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
+ key, controller.getClass().getSimpleName()));
+ return;
+ }
+ controller.updateState(preference);
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
index f69eac749fa..7c2464c1bb3 100644
--- a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
@@ -16,17 +16,29 @@
package com.android.settings.notification;
+import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.icu.text.ListFormatter;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
-import android.util.Log;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.utils.AnnotationSpan;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
@@ -34,11 +46,13 @@ import java.util.List;
import java.util.Objects;
public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePreferenceController {
+ static final String KEY = "footer_preference";
+ private FragmentManager mFragment;
- protected static final String KEY = "footer_preference";
-
- public ZenModeSettingsFooterPreferenceController(Context context, Lifecycle lifecycle) {
+ public ZenModeSettingsFooterPreferenceController(Context context, Lifecycle lifecycle,
+ FragmentManager fragment) {
super(context, KEY, lifecycle);
+ mFragment = fragment;
}
@Override
@@ -70,7 +84,7 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
}
}
- protected String getFooterText() {
+ protected CharSequence getFooterText() {
ZenModeConfig config = getZenModeConfig();
NotificationManager.Policy appliedPolicy = mBackend.getConsolidatedPolicy();
@@ -88,15 +102,25 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
if (rulesNames.size() > 0) {
String rules = ListFormatter.getInstance().format(rulesNames);
if (!rules.isEmpty()) {
- return mContext.getString(R.string.zen_mode_settings_dnd_custom_settings_footer,
- rules);
+ final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
+ AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showCustomSettingsDialog();
+ }
+ });
+ return TextUtils.concat(mContext.getResources().getString(
+ R.string.zen_mode_settings_dnd_custom_settings_footer, rules),
+ AnnotationSpan.linkify(mContext.getResources().getText(
+ R.string.zen_mode_settings_dnd_custom_settings_footer_link),
+ linkInfo));
}
}
}
- return getFooterUsingDefaultPolicy(config);
+ return getDefaultPolicyFooter(config);
}
- private String getFooterUsingDefaultPolicy(ZenModeConfig config) {
+ private String getDefaultPolicyFooter(ZenModeConfig config) {
String footerText = "";
long latestEndTime = -1;
@@ -162,4 +186,101 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
}
return zenRules;
}
+
+ private void showCustomSettingsDialog() {
+ ZenCustomSettingsDialog dialog = new ZenCustomSettingsDialog();
+ dialog.setNotificationPolicy(mBackend.getConsolidatedPolicy());
+ dialog.show(mFragment, ZenCustomSettingsDialog.class.getName());
+ }
+
+ public static class ZenCustomSettingsDialog extends InstrumentedDialogFragment {
+ private String KEY_POLICY = "policy";
+ private NotificationManager.Policy mPolicy;
+ private ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public void setNotificationPolicy(NotificationManager.Policy policy) {
+ mPolicy = policy;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Context context = getActivity();
+ if (savedInstanceState != null) {
+ NotificationManager.Policy policy = savedInstanceState.getParcelable(KEY_POLICY);
+ if (policy != null) {
+ mPolicy = policy;
+ }
+ }
+
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+
+ AlertDialog customSettingsDialog = new AlertDialog.Builder(context)
+ .setTitle(R.string.zen_custom_settings_dialog_title)
+ .setNeutralButton(R.string.zen_custom_settings_dialog_review_schedule,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,
+ int which) {
+ new SubSettingLauncher(context)
+ .setDestination(
+ ZenModeAutomationSettings.class.getName())
+ .setSourceMetricsCategory(
+ MetricsEvent.NOTIFICATION_ZEN_MODE_AUTOMATION)
+ .launch();
+ }
+ })
+ .setPositiveButton(R.string.zen_custom_settings_dialog_ok, null)
+ .setView(LayoutInflater.from(context).inflate(context.getResources().getLayout(
+ R.layout.zen_custom_settings_dialog), null, false))
+ .create();
+
+ customSettingsDialog.setOnShowListener(new DialogInterface.OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialog) {
+ TextView allowCallsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_calls_allow);
+ TextView allowMessagesText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_messages_allow);
+ TextView allowAlarmsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_alarms_allow);
+ TextView allowMediaText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_media_allow);
+ TextView allowSystemText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_system_allow);
+ TextView allowRemindersText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_reminders_allow);
+ TextView allowEventsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_events_allow);
+ TextView notificationsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_show_notifications);
+
+ allowCallsText.setText(mSummaryBuilder.getCallsSettingSummary(mPolicy));
+ allowMessagesText.setText(mSummaryBuilder.getMessagesSettingSummary(mPolicy));
+ allowAlarmsText.setText(getAllowRes(mPolicy.allowAlarms()));
+ allowMediaText.setText(getAllowRes(mPolicy.allowMedia()));
+ allowSystemText.setText(getAllowRes(mPolicy.allowSystem()));
+ allowRemindersText.setText(getAllowRes(mPolicy.allowReminders()));
+ allowEventsText.setText(getAllowRes(mPolicy.allowEvents()));
+ notificationsText.setText(mSummaryBuilder.getBlockedEffectsSummary(mPolicy));
+ }
+ });
+
+ return customSettingsDialog;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_SETTINGS_DIALOG;
+ }
+
+ private int getAllowRes(boolean allow) {
+ return allow ? R.string.zen_mode_sound_summary_on : R.string.zen_mode_sound_summary_off;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(KEY_POLICY, mPolicy);
+ }
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
index 66c2ddd2db4..e5982ebd1a6 100644
--- a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
@@ -23,25 +23,15 @@ import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.icu.text.ListFormatter;
import android.provider.Contacts;
-import android.provider.ContactsContract;
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
public class ZenModeStarredContactsPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceClickListener {
-
- protected static String KEY;
private Preference mPreference;
private final int mPriorityCategory;
private final PackageManager mPackageManager;
@@ -52,8 +42,6 @@ public class ZenModeStarredContactsPreferenceController extends
public ZenModeStarredContactsPreferenceController(Context context, Lifecycle lifecycle, int
priorityCategory, String key) {
super(context, key, lifecycle);
- KEY = key;
-
mPriorityCategory = priorityCategory;
mPackageManager = mContext.getPackageManager();
@@ -96,29 +84,7 @@ public class ZenModeStarredContactsPreferenceController extends
@Override
public CharSequence getSummary() {
- List starredContacts = getStarredContacts();
- int numStarredContacts = starredContacts.size();
-
- List displayContacts = new ArrayList<>();
-
- if (numStarredContacts == 0) {
- displayContacts.add(mContext.getString(R.string.zen_mode_from_none));
- } else {
- for (int i = 0; i < 2 && i < numStarredContacts; i++) {
- displayContacts.add(starredContacts.get(i));
- }
-
- if (numStarredContacts == 3) {
- displayContacts.add(starredContacts.get(2));
- } else if (numStarredContacts > 2) {
- displayContacts.add(mContext.getResources().getQuantityString(
- R.plurals.zen_mode_starred_contacts_summary_additional_contacts,
- numStarredContacts - 2, numStarredContacts - 2));
- }
- }
-
- // values in displayContacts must not be null
- return ListFormatter.getInstance().format(displayContacts);
+ return mBackend.getStarredContactsSummary();
}
@Override
@@ -131,39 +97,6 @@ public class ZenModeStarredContactsPreferenceController extends
return true;
}
- @VisibleForTesting
- List getStarredContacts(Cursor cursor) {
- List starredContacts = new ArrayList<>();
- if (cursor.moveToFirst()) {
- do {
- String contact = cursor.getString(0);
- if (contact != null) {
- starredContacts.add(contact);
- }
- } while (cursor.moveToNext());
- }
- return starredContacts;
- }
-
- private List getStarredContacts() {
- Cursor cursor = null;
- try {
- cursor = queryData();
- return getStarredContacts(cursor);
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- private Cursor queryData() {
- return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
- new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
- ContactsContract.Data.STARRED + "=1", null,
- ContactsContract.Data.TIMES_CONTACTED);
- }
-
private boolean isIntentValid() {
return mStarredContactsIntent.resolveActivity(mPackageManager) != null
|| mFallbackIntent.resolveActivity(mPackageManager) != null;
diff --git a/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java b/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java
new file mode 100644
index 00000000000..b27c5feb0e0
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCallsPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final String[] mListValues;
+
+ public ZenRuleCallsPreferenceController(Context context, String key, Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ mListValues = context.getResources().getStringArray(
+ com.android.settings.R.array.zen_mode_contacts_values);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ updateFromContactsValue(preference);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
+ int allowCalls = ZenModeBackend.getZenPolicySettingFromPrefKey(
+ selectedContactsFrom.toString());
+ mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_CALLS,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allowCalls),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowCalls(allowCalls)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ updateFromContactsValue(preference);
+ return true;
+ }
+
+ private void updateFromContactsValue(Preference preference) {
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ ListPreference listPreference = (ListPreference) preference;
+ listPreference.setSummary(mBackend.getContactsCallsSummary(mRule.getZenPolicy()));
+ final String currentVal = ZenModeBackend.getKeyFromZenPolicySetting(
+ mRule.getZenPolicy().getPriorityCallSenders());
+ listPreference.setValue(mListValues[getIndexOfSendersValue(currentVal)]);
+
+ }
+
+ @VisibleForTesting
+ protected int getIndexOfSendersValue(String currentVal) {
+ int index = 3; // defaults to "none" based on R.array.zen_mode_contacts_values
+ for (int i = 0; i < mListValues.length; i++) {
+ if (TextUtils.equals(currentVal, mListValues[i])) {
+ return i;
+ }
+ }
+
+ return index;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java b/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java
new file mode 100644
index 00000000000..39de0eb65ee
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCustomPolicyPreferenceController extends
+ AbstractZenCustomRulePreferenceController {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleCustomPolicyPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnGearClickListener(p -> {
+ setCustomPolicy();
+ launchCustomSettings();
+
+ });
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ setCustomPolicy();
+ launchCustomSettings();
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null) {
+ return;
+ }
+
+ mPreference.setChecked(mRule.getZenPolicy() != null);
+ }
+
+ private void setCustomPolicy() {
+ if (mRule.getZenPolicy() == null) {
+ mRule.setZenPolicy(mBackend.setDefaultZenPolicy(new ZenPolicy()));
+ mBackend.updateZenRule(mId, mRule);
+ }
+ }
+
+ private void launchCustomSettings() {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleConfigSettings.class.getName())
+ .setArguments(createBundle())
+ .setSourceMetricsCategory(MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_SOUND_SETTINGS)
+ .launch();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java b/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java
new file mode 100644
index 00000000000..804469e37d9
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCustomSwitchPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceChangeListener {
+
+ private @ZenPolicy.PriorityCategory int mCategory;
+ private int mMetricsCategory;
+
+ public ZenRuleCustomSwitchPreferenceController(Context context, Lifecycle lifecycle,
+ String key, @ZenPolicy.PriorityCategory int category, int metricsCategory) {
+ super(context, key, lifecycle);
+ mCategory = category;
+ mMetricsCategory = metricsCategory;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ SwitchPreference pref = (SwitchPreference) preference;
+ pref.setChecked(mRule.getZenPolicy().isCategoryAllowed(mCategory, false));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean allow = (Boolean) newValue;
+ if (ZenModeSettingsBase.DEBUG) {
+ Log.d(TAG, KEY + " onPrefChange mRule=" + mRule + " mCategory=" + mCategory
+ + " allow=" + allow);
+ }
+ mMetricsFeatureProvider.action(mContext, mMetricsCategory,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allow ? 1 : 0),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowCategory(mCategory, allow)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java b/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java
new file mode 100644
index 00000000000..857d8534c23
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleDefaultPolicyPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleDefaultPolicyPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mRule.setZenPolicy(null);
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null) {
+ return;
+ }
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ZEN_CUSTOM_RULE_DEFAULT_SETTINGS,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mPreference.setChecked(mRule.getZenPolicy() == null);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java b/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java
new file mode 100644
index 00000000000..010e152344f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleMessagesPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final String[] mListValues;
+
+ public ZenRuleMessagesPreferenceController(Context context, String key, Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ mListValues = context.getResources().getStringArray(
+ com.android.settings.R.array.zen_mode_contacts_values);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ updateFromContactsValue(preference);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
+ int allowMessages = ZenModeBackend.getZenPolicySettingFromPrefKey(
+ selectedContactsFrom.toString());
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_MESSAGES,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allowMessages),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowMessages(allowMessages)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ updateFromContactsValue(preference);
+ return true;
+ }
+
+ private void updateFromContactsValue(Preference preference) {
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ ListPreference listPreference = (ListPreference) preference;
+ listPreference.setSummary(mBackend.getContactsMessagesSummary(mRule.getZenPolicy()));
+ final String currentVal = ZenModeBackend.getKeyFromZenPolicySetting(
+ mRule.getZenPolicy().getPriorityMessageSenders());
+ listPreference.setValue(mListValues[getIndexOfSendersValue(currentVal)]);
+
+ }
+
+ @VisibleForTesting
+ protected int getIndexOfSendersValue(String currentVal) {
+ int index = 3; // defaults to "none" based on R.array.zen_mode_contacts_values
+ for (int i = 0; i < mListValues.length; i++) {
+ if (TextUtils.equals(currentVal, mListValues[i])) {
+ return i;
+ }
+ }
+
+ return index;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java b/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java
new file mode 100644
index 00000000000..678bf90edaf
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleNotifFooterPreferenceController extends
+ AbstractZenCustomRulePreferenceController {
+
+ public ZenRuleNotifFooterPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable() || mRule.getZenPolicy() == null) {
+ return false;
+ }
+
+
+ return mRule.getZenPolicy().shouldHideAllVisualEffects()
+ || mRule.getZenPolicy().shouldShowAllVisualEffects();
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ if (mRule.getZenPolicy().shouldShowAllVisualEffects()) {
+ preference.setTitle(R.string.zen_mode_restrict_notifications_mute_footer);
+ } else if (mRule.getZenPolicy().shouldHideAllVisualEffects()) {
+ preference.setTitle(R.string.zen_mode_restrict_notifications_hide_footer);
+ } else {
+ preference.setTitle(null);
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java b/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java
new file mode 100644
index 00000000000..1161bec195f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleRepeatCallersPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceChangeListener {
+
+ private final int mRepeatCallersThreshold;
+
+ public ZenRuleRepeatCallersPreferenceController(Context context,
+ String key, Lifecycle lifecycle, int repeatCallersThreshold) {
+ super(context, key, lifecycle);
+ mRepeatCallersThreshold = repeatCallersThreshold;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ setRepeatCallerSummary(screen.findPreference(KEY));
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ SwitchPreference pref = (SwitchPreference) preference;
+ boolean anyCallersCanBypassDnd = mRule.getZenPolicy().getPriorityCallSenders()
+ == ZenPolicy.PEOPLE_TYPE_ANYONE;
+
+ // if any caller can bypass dnd then repeat callers preference is disabled
+ if (anyCallersCanBypassDnd) {
+ pref.setEnabled(false);
+ pref.setChecked(true);
+ } else {
+ pref.setEnabled(true);
+ pref.setChecked(mRule.getZenPolicy().getPriorityCategoryRepeatCallers()
+ == ZenPolicy.STATE_ALLOW);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean allow = (Boolean) newValue;
+ if (ZenModeSettingsBase.DEBUG) {
+ Log.d(TAG, KEY + " onPrefChange mRule=" + mRule + " mCategory="
+ + ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS + " allow=" + allow);
+ }
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_REPEAT_CALLS,
+ Pair.create(MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allow ? 1 : 0),
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowRepeatCallers(allow)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+
+ private void setRepeatCallerSummary(Preference preference) {
+ preference.setSummary(mContext.getString(
+ com.android.settings.R.string.zen_mode_repeat_callers_summary,
+ mRepeatCallersThreshold));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java b/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java
new file mode 100644
index 00000000000..8a227a17ec6
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Contacts;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleStarredContactsPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceClickListener {
+
+ private Preference mPreference;
+ private final @ZenPolicy.PriorityCategory int mPriorityCategory;
+ private final PackageManager mPackageManager;
+
+ private Intent mStarredContactsIntent;
+ private Intent mFallbackIntent;
+
+ public ZenRuleStarredContactsPreferenceController(Context context, Lifecycle lifecycle,
+ @ZenPolicy.PriorityCategory int priorityCategory, String key) {
+ super(context, key, lifecycle);
+ mPriorityCategory = priorityCategory;
+ mPackageManager = mContext.getPackageManager();
+
+ mStarredContactsIntent = new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION);
+
+ mFallbackIntent = new Intent(Intent.ACTION_MAIN);
+ mFallbackIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(KEY);
+
+ if (mPreference != null) {
+ mPreference.setOnPreferenceClickListener(this);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable() || mRule.getZenPolicy() == null || !isIntentValid()) {
+ return false;
+ }
+
+ if (mPriorityCategory == ZenPolicy.PRIORITY_CATEGORY_CALLS) {
+ return mRule.getZenPolicy().getPriorityCallSenders() == ZenPolicy.PEOPLE_TYPE_STARRED;
+ } else if (mPriorityCategory == ZenPolicy.PRIORITY_CATEGORY_MESSAGES) {
+ return mRule.getZenPolicy().getPriorityMessageSenders()
+ == ZenPolicy.PEOPLE_TYPE_STARRED;
+ } else {
+ // invalid category
+ return false;
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mBackend.getStarredContactsSummary();
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (mStarredContactsIntent.resolveActivity(mPackageManager) != null) {
+ mContext.startActivity(mStarredContactsIntent);
+ } else {
+ mContext.startActivity(mFallbackIntent);
+ }
+ return true;
+ }
+
+ private boolean isIntentValid() {
+ return mStarredContactsIntent.resolveActivity(mPackageManager) != null
+ || mFallbackIntent.resolveActivity(mPackageManager) != null;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java
new file mode 100644
index 00000000000..94b82347984
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.CheckBoxPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.widget.DisabledCheckBoxPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final int mMetricsCategory;
+
+ @VisibleForTesting protected @ZenPolicy.VisualEffect int mEffect;
+
+ // if any of these effects are suppressed, this effect must be too
+ @VisibleForTesting protected @ZenPolicy.VisualEffect int[] mParentSuppressedEffects;
+
+ public ZenRuleVisEffectPreferenceController(Context context, Lifecycle lifecycle, String key,
+ @ZenPolicy.VisualEffect int visualEffect, int metricsCategory,
+ @ZenPolicy.VisualEffect int[] parentSuppressedEffects) {
+ super(context, key, lifecycle);
+ mEffect = visualEffect;
+ mMetricsCategory = metricsCategory;
+ mParentSuppressedEffects = parentSuppressedEffects;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable()) {
+ return false;
+ }
+
+ if (mEffect == ZenPolicy.VISUAL_EFFECT_LIGHTS) {
+ return mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed);
+ }
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ boolean suppressed = !mRule.getZenPolicy().isVisualEffectAllowed(mEffect, false);
+ boolean parentSuppressed = false;
+ if (mParentSuppressedEffects != null) {
+ for (@ZenPolicy.VisualEffect int parentEffect : mParentSuppressedEffects) {
+ if (!mRule.getZenPolicy().isVisualEffectAllowed(parentEffect, true)) {
+ parentSuppressed = true;
+ }
+ }
+ }
+ if (parentSuppressed) {
+ ((CheckBoxPreference) preference).setChecked(parentSuppressed);
+ onPreferenceChange(preference, parentSuppressed);
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(false);
+ } else {
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(true);
+ ((CheckBoxPreference) preference).setChecked(suppressed);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean suppressEffect = (Boolean) newValue;
+ mMetricsFeatureProvider.action(mContext, mMetricsCategory,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION,
+ suppressEffect ? 1 : 0),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showVisualEffect(mEffect, !suppressEffect)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java
new file mode 100644
index 00000000000..9ddd624e421
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsAllPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsAllPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SOUND_ONLY,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showAllVisualEffects()
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ mPreference.setChecked(mRule.getZenPolicy().shouldShowAllVisualEffects());
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java
new file mode 100644
index 00000000000..64dd71c004f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsCustomPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsCustomPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnGearClickListener(p -> {
+ launchCustomSettings();
+
+ });
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ launchCustomSettings();
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ mPreference.setChecked(!mRule.getZenPolicy().shouldHideAllVisualEffects()
+ && !mRule.getZenPolicy().shouldShowAllVisualEffects());
+ }
+
+ private void launchCustomSettings() {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SHOW_CUSTOM,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleBlockedEffectsSettings.class.getName())
+ .setArguments(createBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_VIS_EFFECTS)
+ .launch();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java
new file mode 100644
index 00000000000..4f98924c5f8
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsNonePreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsNonePreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SOUND_AND_VIS_EFFECTS,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .hideAllVisualEffects()
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ mPreference.setChecked(mRule.getZenPolicy().shouldHideAllVisualEffects());
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index ab06f751c77..447de0049df 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -54,6 +54,12 @@ com.android.settings.notification.NotificationStation
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
com.android.settings.notification.ZenModeEventRuleSettings
com.android.settings.notification.ZenModeScheduleRuleSettings
+com.android.settings.notification.ZenCustomRuleNotificationsSettings
+com.android.settings.notification.ZenCustomRuleCallsSettings
+com.android.settings.notification.ZenCustomRuleConfigSettings
+com.android.settings.notification.ZenCustomRuleSettings
+com.android.settings.notification.ZenCustomRuleBlockedEffectsSettings
+com.android.settings.notification.ZenCustomRuleMessagesSettings
com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$InternalActivity$InternalSetupChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
index 6169f92ddc9..6cf19a629a5 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -1,26 +1,58 @@
package com.android.settings.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.database.Cursor;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class ZenModeBackendTest {
+ @Mock
+ private NotificationManager mNotificationManager;
private static final String GENERIC_RULE_NAME = "test";
private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+ private Context mContext;
+ private ZenModeBackend mBackend;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mBackend = new ZenModeBackend(mContext);
+ }
+
@Test
public void updateState_checkRuleOrderingDescending() {
final int NUM_RULES = 4;
@@ -63,6 +95,39 @@ public class ZenModeBackendTest {
}
}
+ @Test
+ public void updateSummary_nullCursorValues() {
+ Cursor testCursorWithNullValues = createMockCursor(3);
+ when(testCursorWithNullValues.getString(0)).thenReturn(null);
+
+ // expected - no null values
+ List contacts = mBackend.getStarredContacts(testCursorWithNullValues);
+ for (String contact : contacts) {
+ assertThat(contact).isNotNull();
+ }
+ }
+
+ private Cursor createMockCursor(int size) {
+ Cursor mockCursor = mock(Cursor.class);
+ when(mockCursor.moveToFirst()).thenReturn(true);
+
+ doAnswer(new Answer() {
+ int count = 0;
+
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ if (count < size) {
+ count++;
+ return true;
+ }
+ return false;
+ }
+
+ }).when(mockCursor).moveToNext();
+
+ return mockCursor;
+ }
+
private Map.Entry[] populateAutoZenRulesAscendingCreationTime(
int numRules, boolean addDefaultRules) {
Map ruleMap = new HashMap<>();
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
index 5589caefa0f..808766da22e 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
@@ -17,12 +17,16 @@
package com.android.settings.notification;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
+import androidx.preference.Preference;
+
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -67,11 +71,10 @@ public final class ZenModeMessagesPreferenceControllerTest {
assertTrue(mController.isAvailable());
}
-// TODO: (b/111475013 - beverlyt) set messages summary
-// @Test
-// public void testHasSummary() {
-// Preference pref = mock(Preference.class);
-// mController.updateState(pref);
-// verify(pref).setSummary(any());
-// }
+ @Test
+ public void testHasSummary() {
+ Preference pref = mock(Preference.class);
+ mController.updateState(pref);
+ verify(pref).setSummary(any());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
index 516d98f1f0a..345186852c2 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
@@ -22,9 +22,8 @@ import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
-import static org.junit.Assert.assertTrue;
-
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +39,7 @@ import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ZenRule;
import android.util.ArrayMap;
+import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -92,8 +92,8 @@ public class ZenModeSettingsFooterPreferenceControllerTest {
mContentResolver = RuntimeEnvironment.application.getContentResolver();
when(mNotificationManager.getZenModeConfig()).thenReturn(mZenModeConfig);
- mController =
- new ZenModeSettingsFooterPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeSettingsFooterPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
ReflectionHelpers.setField(mZenModeConfig, AUTOMATIC_RULES_FIELD, mInjectedAutomaticRules);
ReflectionHelpers.setField(mController, "mZenModeConfigWrapper", mConfigWrapper);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
index db551a2f8ff..fd6e63943ca 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
@@ -30,7 +30,6 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -49,7 +48,6 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
-import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class ZenModeStarredContactsPreferenceControllerTest {
@@ -156,18 +154,6 @@ public class ZenModeStarredContactsPreferenceControllerTest {
assertThat(mMessagesController.isAvailable()).isTrue();
}
- @Test
- public void updateSummary_nullCursorValues() {
- Cursor testCursorWithNullValues = createMockCursor(3);
- when(testCursorWithNullValues.getString(0)).thenReturn(null);
-
- // expected - no null values
- List contacts = mMessagesController.getStarredContacts(testCursorWithNullValues);
- for (String contact : contacts) {
- assertThat(contact).isNotNull();
- }
- }
-
@Test
public void nullPreference_displayPreference() {
when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
@@ -176,25 +162,4 @@ public class ZenModeStarredContactsPreferenceControllerTest {
// should not throw a null pointer
mMessagesController.displayPreference(mPreferenceScreen);
}
-
- private Cursor createMockCursor(int size) {
- Cursor mockCursor = mock(Cursor.class);
- when(mockCursor.moveToFirst()).thenReturn(true);
-
- doAnswer(new Answer() {
- int count = 0;
-
- @Override
- public Boolean answer(InvocationOnMock invocation) {
- if (count < size) {
- count++;
- return true;
- }
- return false;
- }
-
- }).when(mockCursor).moveToNext();
-
- return mockCursor;
- }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java
new file mode 100644
index 00000000000..5d3a6017c9e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleCustomPolicyPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private ZenRuleCustomPolicyPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleCustomPolicyPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_nullZenPolicy() {
+ updateControllerZenPolicy(null);
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_hasZenPolicy() {
+ updateControllerZenPolicy(new ZenPolicy.Builder().build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java
new file mode 100644
index 00000000000..10472a5b695
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.service.notification.ZenPolicy;
+
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+abstract class ZenRuleCustomPrefContrTestBase {
+ public static final String RULE_ID = "test_rule_id";
+ public static final String PREF_KEY = "main_pref";
+
+ AutomaticZenRule mRule = new AutomaticZenRule("test", null, null, null, null,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+
+ abstract AbstractZenCustomRulePreferenceController getController();
+
+ void updateControllerZenPolicy(ZenPolicy policy) {
+ mRule.setZenPolicy(policy);
+ getController().onResume(mRule, RULE_ID);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java
new file mode 100644
index 00000000000..e15eb605936
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleCustomSwitchPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+ private ZenRuleCustomSwitchPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private SwitchPreference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ mController = new ZenRuleCustomSwitchPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, ZenPolicy.PRIORITY_CATEGORY_ALARMS, 0);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChanged_enable() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(false)
+ .build());
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_disable() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(true)
+ .build());
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java
new file mode 100644
index 00000000000..e350793b0e3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleDefaultPolicyPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private ZenRuleDefaultPolicyPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleDefaultPolicyPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_nullZenPolicy() {
+ updateControllerZenPolicy(null);
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_hasZenPolicy() {
+ updateControllerZenPolicy(new ZenPolicy.Builder().build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java
new file mode 100644
index 00000000000..5d070e56699
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.content.Context;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRulePreferenceControllerTest {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private TestablePreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new TestablePreferenceController(mContext,"test", mock(Lifecycle.class));
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void onResumeTest() {
+ final String id = "testid";
+ final AutomaticZenRule rule = new AutomaticZenRule("test", null, null,
+ null, null, NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+
+ assertTrue(mController.mRule == null);
+ assertTrue(mController.mId == null);
+
+ mController.onResume(rule, id);
+
+ assertEquals(mController.mId, id);
+ assertEquals(mController.mRule, rule);
+ }
+
+ class TestablePreferenceController extends AbstractZenCustomRulePreferenceController {
+ TestablePreferenceController(Context context, String key,
+ Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java
new file mode 100644
index 00000000000..45062d4f456
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleRepeatCallersPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private ZenRuleRepeatCallersPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private SwitchPreference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ mController = new ZenRuleRepeatCallersPreferenceController(mContext, PREF_KEY,
+ mock(Lifecycle.class), 15);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(anyString())).thenReturn(mRule);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+ mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void updateState_Priority_anyCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .allowRepeatCallers(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setEnabled(false);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void onPreferenceChanged_EnableRepeatCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(false)
+ .build());
+ mController.updateState(mockPref);
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_DisableRepeatCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(true)
+ .build());
+ mController.updateState(mockPref);
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java
new file mode 100644
index 00000000000..6c422eb2412
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleStarredContactsPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private ZenRuleStarredContactsPreferenceController mCallsController;
+ private ZenRuleStarredContactsPreferenceController mMessagesController;
+ private static int CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private Preference mockPref;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private Intent testIntent;
+ @Mock
+ private ComponentName mComponentName;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ if (CURR_CONTROLLER == ZenPolicy.PRIORITY_CATEGORY_MESSAGES) {
+ return mMessagesController;
+ } else {
+ return mCallsController;
+ }
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(testIntent.resolveActivity(any())).thenReturn(mComponentName);
+
+ mCallsController = new ZenRuleStarredContactsPreferenceController(
+ mContext, mock(Lifecycle.class), ZenPolicy.PRIORITY_CATEGORY_CALLS,
+ "zen_mode_starred_contacts_callers");
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ ReflectionHelpers.setField(mCallsController, "mBackend", mBackend);
+ ReflectionHelpers.setField(mCallsController, "mStarredContactsIntent", testIntent);
+ when(mPreferenceScreen.findPreference(mCallsController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mCallsController.displayPreference(mPreferenceScreen);
+
+ mMessagesController = new ZenRuleStarredContactsPreferenceController(
+ mContext, mock(Lifecycle.class), ZenPolicy.PRIORITY_CATEGORY_MESSAGES,
+ "zen_mode_starred_contacts_messages");
+ ReflectionHelpers.setField(mMessagesController, "mBackend", mBackend);
+ ReflectionHelpers.setField(mMessagesController, "mStarredContactsIntent", testIntent);
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mMessagesController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void isAvailable_noCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)
+ .build());
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_anyCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .build());
+
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_starredCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED)
+ .build());
+
+ assertThat(mCallsController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_noMessages() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_NONE)
+ .build());
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_anyMessages() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .build());
+
+ assertThat(mMessagesController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_starredMessageContacts() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED)
+ .build());
+
+ assertThat(mMessagesController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void nullPreference_displayPreference() {
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(null);
+
+ // should not throw a null pointer
+ mMessagesController.displayPreference(mPreferenceScreen);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java
new file mode 100644
index 00000000000..c99d20724a9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.widget.DisabledCheckBoxPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private static final @ZenPolicy.VisualEffect int EFFECT_PEEK = ZenPolicy.VISUAL_EFFECT_PEEK;
+ private static final @ZenPolicy.VisualEffect int PARENT_EFFECT1 = ZenPolicy.VISUAL_EFFECT_BADGE;
+ private static final @ZenPolicy.VisualEffect int PARENT_EFFECT2 =
+ ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST;
+ private static final int PREF_METRICS = 1;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private DisabledCheckBoxPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ NotificationManager mNotificationManager;
+
+ private Context mContext;
+ private ZenRuleVisEffectPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(
+ mock(NotificationManager.Policy.class));
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, EFFECT_PEEK, PREF_METRICS, null);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void isAvailable() {
+ // VISUAL_EFFECT_PEEK isn't available until after onResume is called
+ assertFalse(mController.isAvailable());
+ updateControllerZenPolicy(new ZenPolicy()); // calls onResume
+ assertTrue(mController.isAvailable());
+
+ // VISUAL_EFFECT_LIGHTS is only available if the device has an LED:
+ Context mockContext = mock(Context.class);
+ mController = new ZenRuleVisEffectPreferenceController(mockContext, mock(Lifecycle.class),
+ PREF_KEY, ZenPolicy.VISUAL_EFFECT_LIGHTS, PREF_METRICS, null);
+ updateControllerZenPolicy(new ZenPolicy()); // calls onResume
+
+ Resources mockResources = mock(Resources.class);
+ when(mockContext.getResources()).thenReturn(mockResources);
+
+ when(mockResources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed))
+ .thenReturn(false); // no light
+ assertFalse(mController.isAvailable());
+
+ when(mockResources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed))
+ .thenReturn(true); // has light
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void updateState_notChecked() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void updateState_checked() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentChecked() {
+ mController.mParentSuppressedEffects = new int[]{PARENT_EFFECT1, PARENT_EFFECT2};
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showVisualEffect(EFFECT_PEEK, true)
+ .showVisualEffect(PARENT_EFFECT1, true)
+ .showVisualEffect(PARENT_EFFECT2, false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).enableCheckbox(false);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentNotChecked() {
+ mController.mParentSuppressedEffects = new int[]{PARENT_EFFECT1, PARENT_EFFECT2};
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showVisualEffect(EFFECT_PEEK, true)
+ .showVisualEffect(PARENT_EFFECT1, true)
+ .showVisualEffect(PARENT_EFFECT2, true)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedFalse() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(false)
+ .build());
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showPeeking(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedTrue() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .build());
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showPeeking(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java
new file mode 100644
index 00000000000..5ef6194e56f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsAllPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsAllPreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsAllPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_customEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java
new file mode 100644
index 00000000000..79ef8d2da5b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsCustomPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsCustomPreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsCustomPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_customEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java
new file mode 100644
index 00000000000..d66433eea62
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsNonePreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsNonePreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsNonePreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_custom() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ }
+}