diff --git a/res/layout/zen_mode_settings_button.xml b/res/layout/zen_mode_settings_button.xml
index 49aa28779aa..72731cc6c2d 100644
--- a/res/layout/zen_mode_settings_button.xml
+++ b/res/layout/zen_mode_settings_button.xml
@@ -39,7 +39,6 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:paddingTop="@dimen/zen_mode_button_padding_vertical"
android:text="@string/zen_mode_button_turn_on"/>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5c2aafea51d..6aa42f42846 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7757,13 +7757,13 @@
Automatically caption media
-
- Never
+
+ None
-
+
- - 1 enabled
- - %d enabled
+ - 1 schedule set
+ - %d schedules set
@@ -7778,26 +7778,8 @@
Turn on Do Not Disturb
-
- Exceptions
-
-
- Default duration
-
-
- Allow sounds and vibrations from
-
-
- No sound
-
-
- Total Silence
-
-
- No sound except %1$s
-
- No sound except alarms and media
+ Alarms and media sounds can interrupt
Schedules
@@ -7832,15 +7814,6 @@
Use schedule
-
- Priority only
-
-
- Alarms only
-
-
- Total silence
-
%1$s: %2$s
@@ -7853,8 +7826,8 @@
Allow interruptions that make sound
-
- Restrict notifications
+
+ Display options for hidden notifications
No sound from notifications
@@ -7993,7 +7966,7 @@
- Exceptions when Do Not Disturb is on
+ What can interrupt Do Not Disturb
People
@@ -8002,23 +7975,12 @@
Alarms & other interruptions
Schedules
-
- Silenced notifications
+
+ Set duration for Quick Settings
When Do Not Disturb is on, sound and vibration will be muted, except for the items you allow above.
-
- Mute all except
-
- Muted
-
- Not muted
-
- Muted, but allow %1$s
-
- Muted, but allow %1$s and %2$s
-
- Muted, but allow %1$s, %2$s, and %3$s
Custom settings
@@ -8923,19 +8885,15 @@
Allow calls
-
Calls
-
To be sure allowed calls make sound, check whether your device is set to ring, vibrate, or silent.
-
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
-
- 1 other
@@ -8949,128 +8907,119 @@
Allow messages
-
To be sure allowed messages make sound, check whether your device is set to ring, vibrate, or silent.
-
For \u2018%1$s\u2019 incoming messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
-
SMS, MMS, and messaging apps
From anyone
-
From contacts only
-
From starred contacts only
From starred contacts and repeat callers
-
From contacts and repeat callers
-
From repeat callers only
None
-
Don\u2019t allow any calls
-
Don\u2019t allow any messages
Alarms
-
From timers, alarms, security systems, and other apps
-
alarms
Media sounds
-
From videos, games, and other media
-
media
Touch sounds
-
From your keyboard and other buttons
-
touch sounds
Reminders
-
From tasks and reminders
-
reminders
Events
-
From upcoming calendar events
-
-
- Allow apps to override
-
-
- App exceptions
-
-
- No apps can override Do Not Disturb
-
-
-
- - No 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
-
-
events
-
- anyone
+
+ Allow apps to override
+
+ No apps can interrupt
+
+
+ - %s can interrupt
+ - %s can interrupt
+
+
+ %d more
+
+ App exceptions
-
- contacts
+
+
+ - %s can interrupt
+ - %s can interrupt
+
+
+ Nothing can interrupt
+
+ %d more
-
- starred contacts
+
+ No one can interrupt
+
+ Some people can interrupt
+
+ All people can interrupt
Repeat callers
-
-
- repeat callers
-
Allow repeat callers
-
+
+ anyone
+
+ contacts
+
+ starred contacts
+
+ repeat callers
Allow from %1$s
-
Allow from %1$s and %2$s
-
If the same person calls a second time within a %d minute period
@@ -9079,43 +9028,33 @@
Automatically turn on
-
Never
-
Every night
-
Weeknights
-
Start time
-
End time
-
%s next day
Change to alarms only indefinitely
-
- Change to alarms only for one minute until %2$s
- Change to alarms only for %1$d minutes (until %2$s)
-
- Change to alarms only for one hour until %2$s
- Change to alarms only for %1$d hours until %2$s
-
Change to alarms only until %1$s
-
Change to always interrupt
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index ce2d1322c9a..9649207dbbb 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -26,7 +26,6 @@
android:title="@string/zen_mode_settings_title"
android:selectable="false"
android:layout="@layout/zen_mode_settings_button"
- settings:allowDividerAbove="true"
settings:allowDividerBelow="true"
settings:keywords="@string/keywords_zen_mode_settings"/>
@@ -55,26 +54,26 @@
+ settings:initialExpandedChildrenCount="0">
+
+
+
-
-
-
diff --git a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
index a93fa1b9856..7459394d701 100644
--- a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
@@ -1,19 +1,53 @@
package com.android.settings.notification.zen;
+import android.app.Application;
+import android.app.NotificationChannel;
import android.content.Context;
-import android.os.UserHandle;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.text.TextUtils;
+import androidx.core.text.BidiFormatter;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
-public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController {
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Apps
+ */
+public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController
+ implements PreferenceControllerMixin {
protected static final String KEY = "zen_mode_behavior_apps";
+
+ @VisibleForTesting protected Preference mPreference;
+ private ApplicationsState.Session mAppSession;
private NotificationBackend mNotificationBackend = new NotificationBackend();
- public ZenModeBypassingAppsPreferenceController(Context context, Lifecycle lifecycle) {
+ private String mSummary;
+
+ public ZenModeBypassingAppsPreferenceController(Context context, Application app,
+ Fragment host, Lifecycle lifecycle) {
+ this(context, app == null ? null : ApplicationsState.getInstance(app), host, lifecycle);
+ }
+
+ private ZenModeBypassingAppsPreferenceController(Context context, ApplicationsState appState,
+ Fragment host, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
+ if (appState != null && host != null) {
+ mAppSession = appState.newSession(mAppSessionCallbacks, host.getLifecycle());
+ }
}
@Override
@@ -22,13 +56,125 @@ public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePre
}
@Override
- public String getSummary() {
- final int channelsBypassing =
- mNotificationBackend.getNumAppsBypassingDnd(UserHandle.getCallingUserId());
- if (channelsBypassing == 0) {
- return mContext.getResources().getString(R.string.zen_mode_bypassing_apps_subtext_none);
- }
- return mContext.getResources().getQuantityString(R.plurals.zen_mode_bypassing_apps_subtext,
- channelsBypassing, channelsBypassing);
+ public String getPreferenceKey() {
+ return KEY;
}
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPreference = screen.findPreference(KEY);
+ updateAppsBypassingDndSummaryText();
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public String getSummary() {
+ return mSummary;
+ }
+
+ private void updateAppsBypassingDndSummaryText() {
+ if (mAppSession == null) {
+ return;
+ }
+
+ ApplicationsState.AppFilter filter = ApplicationsState.FILTER_ALL_ENABLED;
+ List apps = mAppSession.rebuild(filter,
+ ApplicationsState.ALPHA_COMPARATOR);
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @VisibleForTesting
+ void updateAppsBypassingDndSummaryText(List apps) {
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ case Settings.Global.ZEN_MODE_ALARMS:
+ // users cannot change their DND settings when an app puts the device total
+ // silence or alarms only (both deprecated) modes
+ mPreference.setEnabled(false);
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ return;
+ default:
+ mPreference.setEnabled(true);
+ }
+
+ if (apps == null) {
+ return;
+ }
+
+ List appsBypassingDnd = new ArrayList<>();
+ for (ApplicationsState.AppEntry entry : apps) {
+ String pkg = entry.info.packageName;
+ for (NotificationChannel channel : mNotificationBackend
+ .getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList()) {
+ if (!TextUtils.isEmpty(channel.getConversationId())) {
+ // conversation channels that bypass dnd will be shown on the People page
+ continue;
+ }
+ appsBypassingDnd.add(BidiFormatter.getInstance().unicodeWrap(entry.label));
+ continue;
+ }
+ }
+
+ if (appsBypassingDnd.size() == 0) {
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ refreshSummary(mPreference);
+ return;
+ }
+
+ List displayAppsBypassing = new ArrayList<>();
+ if (appsBypassingDnd.size() <= 2) {
+ displayAppsBypassing = appsBypassingDnd;
+ } else {
+ displayAppsBypassing.add(appsBypassingDnd.get(0));
+ displayAppsBypassing.add(appsBypassingDnd.get(1));
+ displayAppsBypassing.add(mContext.getResources().getString(
+ R.string.zen_mode_apps_bypassing_list_count,
+ appsBypassingDnd.size() - 2));
+ }
+ mSummary = mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_bypassing_apps_subtext,
+ appsBypassingDnd.size(),
+ ListFormatter.getInstance().format(displayAppsBypassing));
+ refreshSummary(mPreference);
+ }
+
+ private final ApplicationsState.Callbacks mAppSessionCallbacks =
+ new ApplicationsState.Callbacks() {
+
+ @Override
+ public void onRunningStateChanged(boolean running) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onPackageListChanged() {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onRebuildComplete(ArrayList apps) {
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @Override
+ public void onPackageIconChanged() { }
+
+ @Override
+ public void onPackageSizeChanged(String packageName) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onAllSizesComputed() { }
+
+ @Override
+ public void onLauncherInfoChanged() { }
+
+ @Override
+ public void onLoadEntriesCompleted() {
+ updateAppsBypassingDndSummaryText();
+ }
+ };
}
diff --git a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
index a48c93d5d6b..cb185dd6c4d 100644
--- a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
@@ -16,25 +16,33 @@
package com.android.settings.notification.zen;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > People
+ */
public class ZenModePeoplePreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
private final String KEY;
- private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModePeoplePreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, key, lifecycle);
KEY = key;
- mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
@@ -60,8 +68,28 @@ public class ZenModePeoplePreferenceController extends
break;
default:
preference.setEnabled(true);
- // TODO: How do all of the people options roll up into the summary?
- //preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
+ preference.setSummary(getPeopleSummary());
+ }
+ }
+
+ private String getPeopleSummary() {
+ final int callersAllowed = mBackend.getPriorityCallSenders();
+ final int messagesAllowed = mBackend.getPriorityMessageSenders();
+ final int conversationsAllowed = mBackend.getPriorityConversationSenders();
+ final boolean areRepeatCallersAllowed =
+ mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_REPEAT_CALLERS);
+
+ if (callersAllowed == PRIORITY_SENDERS_ANY
+ && messagesAllowed == PRIORITY_SENDERS_ANY
+ && conversationsAllowed == CONVERSATION_SENDERS_ANYONE) {
+ return mContext.getResources().getString(R.string.zen_mode_people_all);
+ } else if (callersAllowed == ZenModeBackend.SOURCE_NONE
+ && messagesAllowed == ZenModeBackend.SOURCE_NONE
+ && conversationsAllowed == CONVERSATION_SENDERS_NONE
+ && !areRepeatCallersAllowed) {
+ return mContext.getResources().getString(R.string.zen_mode_people_none);
+ } else {
+ return mContext.getResources().getString(R.string.zen_mode_people_some);
}
}
}
diff --git a/src/com/android/settings/notification/zen/ZenModeSettings.java b/src/com/android/settings/notification/zen/ZenModeSettings.java
index 871974b07a4..c92099a6db4 100644
--- a/src/com/android/settings/notification/zen/ZenModeSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSettings.java
@@ -25,15 +25,19 @@ import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
+import android.app.Activity;
+import android.app.Application;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.icu.text.ListFormatter;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
@@ -67,7 +71,9 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
protected List createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager());
+ final Activity activity = getActivity();
+ return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager(),
+ activity != null ? activity.getApplication() : null, this);
}
@Override
@@ -76,15 +82,19 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
private static List buildPreferenceControllers(Context context,
- Lifecycle lifecycle, FragmentManager fragmentManager) {
+ Lifecycle lifecycle, FragmentManager fragmentManager, Application app,
+ Fragment fragment) {
List controllers = new ArrayList<>();
+ controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModePeoplePreferenceController(context, lifecycle,
"zen_mode_behavior_people"));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBypassingAppsPreferenceController(context, app,
+ fragment, lifecycle));
+ controllers.add(new ZenModeSoundVibrationPreferenceController(context, lifecycle,
+ "zen_sound_vibration_settings"));
controllers.add(new ZenModeAutomationPreferenceController(context));
- controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
+ controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
fragmentManager));
return controllers;
@@ -110,29 +120,34 @@ public class ZenModeSettings extends ZenModeSettingsBase {
PRIORITY_CATEGORY_REPEAT_CALLERS,
};
- String getSoundSettingSummary(Policy policy) {
- List enabledCategories = getEnabledCategories(policy,
+ String getOtherSoundCategoriesSummary(Policy policy) {
+ List enabledCategories = getEnabledCategories(
+ policy,
category -> PRIORITY_CATEGORY_ALARMS == category
|| PRIORITY_CATEGORY_MEDIA == category
- || PRIORITY_CATEGORY_SYSTEM == category, false);
+ || PRIORITY_CATEGORY_SYSTEM == category
+ || PRIORITY_CATEGORY_REMINDERS == category
+ || PRIORITY_CATEGORY_EVENTS == category,
+ true);
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_sound_all_muted);
- } else if (numCategories == 1) {
- return mContext.getString(R.string.zen_sound_one_allowed,
- enabledCategories.get(0));
- } else if (numCategories == 2) {
- return mContext.getString(R.string.zen_sound_two_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1));
- } else if (numCategories == 3) {
- return mContext.getString(R.string.zen_sound_three_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1),
- enabledCategories.get(2));
- } else {
- return mContext.getString(R.string.zen_sound_none_muted);
+ return mContext.getResources().getString(R.string.zen_mode_other_sounds_none);
}
+
+ List displayCategories = new ArrayList<>();
+ if (numCategories <= 2) {
+ displayCategories = enabledCategories;
+ } else {
+ displayCategories.add(enabledCategories.get(0));
+ displayCategories.add(enabledCategories.get(1));
+ displayCategories.add(mContext.getString(R.string.zen_mode_other_sounds_list_count,
+ numCategories - 2));
+ }
+
+ return mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_other_sounds_summary,
+ numCategories /* quantity */,
+ ListFormatter.getInstance().format(displayCategories));
}
String getCallsSettingSummary(Policy policy) {
@@ -322,7 +337,8 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public List createPreferenceControllers(Context
context) {
- return buildPreferenceControllers(context, null, null);
+ return buildPreferenceControllers(context, null, null,
+ null, null);
}
};
}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
new file mode 100644
index 00000000000..691c2aede69
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.zen;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Alarms & other interruptions
+ */
+public class ZenModeSoundVibrationPreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+ private final String mKey;
+ private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public ZenModeSoundVibrationPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ mKey = key;
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return mKey;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_other_sounds_none));
+ break;
+ case Settings.Global.ZEN_MODE_ALARMS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_behavior_alarms_only));
+ break;
+ default:
+ preference.setEnabled(true);
+ preference.setSummary(mSummaryBuilder.getOtherSoundCategoriesSummary(getPolicy()));
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
index 3d4f3c2206f..c07ee773c85 100644
--- a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
@@ -21,14 +21,17 @@ import android.content.Context;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Settings > Sound > Do Not Disturb > Alarms & Other Interruptions
+ */
@SearchIndexable
public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implements Indexable {
@@ -40,10 +43,6 @@ public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implement
private static List buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List controllers = new ArrayList<>();
- controllers.add(new ZenModeCallsPreferenceController(context, lifecycle,
- "zen_mode_calls_settings"));
- controllers.add(new ZenModeMessagesPreferenceController(context, lifecycle,
- "zen_mode_messages_settings"));
controllers.add(new ZenModeAlarmsPreferenceController(context, lifecycle,
"zen_mode_alarms"));
controllers.add(new ZenModeMediaPreferenceController(context, lifecycle));
@@ -52,7 +51,6 @@ public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implement
controllers.add(new ZenModeEventsPreferenceController(context, lifecycle));
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle,
R.string.zen_sound_footer));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
return controllers;
}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
index 8760d4ce180..a6efaaf883c 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
@@ -18,16 +18,23 @@ package com.android.settings.notification.zen;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.NotificationChannel;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ParceledListSlice;
+import android.provider.Settings;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
import com.android.settings.notification.NotificationBackend;
-import com.android.settings.notification.zen.ZenModeBypassingAppsPreferenceController;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,6 +44,9 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ZenModeBypassingAppsPreferenceControllerTest {
@@ -45,30 +55,156 @@ public class ZenModeBypassingAppsPreferenceControllerTest {
private Context mContext;
@Mock
private NotificationBackend mBackend;
+ private int mPreviousZenSetting;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
-
- mController = new ZenModeBypassingAppsPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeBypassingAppsPreferenceController(
+ mContext, null, mock(Fragment.class), mock(Lifecycle.class));
+ mController.mPreference = new Preference(mContext);
+ mPreviousZenSetting =
+ Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
ReflectionHelpers.setField(mController, "mNotificationBackend", mBackend);
}
+ @After
+ public void tearDown() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ mPreviousZenSetting);
+ }
+
@Test
public void testIsAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(5);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void testNotAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(0);
- assertThat(mController.isAvailable()).isFalse();
+ public void testUpdateBypassingApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a single app is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app name from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry.label)).isTrue();
}
@Test
- public void testHasSummary() {
- assertThat(mController.getSummary()).isNotNull();
+ public void testUpdateBypassingApps_multipleApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry1 = mock(ApplicationsState.AppEntry.class);
+ entry1.info = new ApplicationInfo();
+ entry1.info.packageName = "test1";
+ entry1.label = "test1";
+ entry1.info.uid = 1;
+ ApplicationsState.AppEntry entry2 = mock(ApplicationsState.AppEntry.class);
+ entry2.info = new ApplicationInfo();
+ entry2.info.packageName = "test2";
+ entry2.label = "test2";
+ entry2.info.uid = 2;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry1);
+ appEntries.add(entry2);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry1.info.packageName,
+ entry1.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry2.info.packageName,
+ entry2.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a list of apps is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app names from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry1.label)).isTrue();
+ assertThat(mController.getSummary().contains(entry2.label)).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_nullAppsList() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is null
+ mController.updateAppsBypassingDndSummaryText(null);
+
+ // THEN the preference is enabled and summary is unchanged (in this case, null)
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary()).isNull();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_emptyAppsList() {
+ // GIVEN the DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is an empty list
+ mController.updateAppsBypassingDndSummaryText(new ArrayList<>());
+
+ // THEN the preference is enabled and summary is updated
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_alarmsOnly() {
+ // GIVEN alarms only DND mode
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_ALARMS);
+
+ // mock app entries
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN we update apps bypassing dnd summary text
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is disabled and the summary says no apps can bypass
+ assertThat(mController.mPreference.isEnabled()).isFalse();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
index da185adedb0..d3c3a85a5ad 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
@@ -97,34 +97,6 @@ public class ZenModeSettingsTest {
.isEqualTo("Allow from starred contacts and repeat callers");
}
- @Test
- public void testGetSoundSettingSummary_allOff() {
- Policy policy = new Policy(0, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOn() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow alarms, media, and touch sounds");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButOne() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted, but allow media");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButTwo() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow media and touch sounds");
- }
-
@Test
public void searchProvider_shouldIndexDefaultXml() {
final List sir = ZenModeSettings.SEARCH_INDEX_DATA_PROVIDER