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); + } +}