Merge "Support device effects for manual mode" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
162813cd5a
@@ -103,8 +103,8 @@ class ZenMode {
|
|||||||
mIsManualDnd = isManualDnd;
|
mIsManualDnd = isManualDnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZenMode manualDndMode(AutomaticZenRule dndPolicyAsRule, boolean isActive) {
|
static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) {
|
||||||
return new ZenMode(MANUAL_DND_MODE_ID, dndPolicyAsRule, isActive, true);
|
return new ZenMode(MANUAL_DND_MODE_ID, manualRule, isActive, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.settings.notification.modes;
|
package com.android.settings.notification.modes;
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.AutomaticZenRule;
|
import android.app.AutomaticZenRule;
|
||||||
@@ -32,11 +30,11 @@ import android.provider.ContactsContract;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.notification.Condition;
|
import android.service.notification.Condition;
|
||||||
import android.service.notification.ConversationChannelWrapper;
|
import android.service.notification.ConversationChannelWrapper;
|
||||||
import android.service.notification.ZenAdapters;
|
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -162,22 +160,19 @@ class ZenModesBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ZenMode getManualDndMode(ZenModeConfig config) {
|
private ZenMode getManualDndMode(ZenModeConfig config) {
|
||||||
// TODO: b/333530553 - Read ZenDeviceEffects of manual DND.
|
ZenModeConfig.ZenRule manualRule = config.manualRule;
|
||||||
// TODO: b/333682392 - Replace with final strings for name & trigger description
|
// TODO: b/333682392 - Replace with final strings for name & trigger description
|
||||||
AutomaticZenRule manualDndRule = new AutomaticZenRule.Builder(
|
AutomaticZenRule manualDndRule = new AutomaticZenRule.Builder(
|
||||||
mContext.getString(R.string.zen_mode_settings_title), Uri.EMPTY)
|
mContext.getString(R.string.zen_mode_settings_title), manualRule.conditionId)
|
||||||
.setType(AutomaticZenRule.TYPE_OTHER)
|
.setType(manualRule.type)
|
||||||
.setZenPolicy(ZenAdapters.notificationPolicyToZenPolicy(
|
.setZenPolicy(manualRule.zenPolicy)
|
||||||
mNotificationManager.getNotificationPolicy()))
|
.setDeviceEffects(manualRule.zenDeviceEffects)
|
||||||
.setDeviceEffects(null)
|
.setManualInvocationAllowed(manualRule.allowManualInvocation)
|
||||||
.setManualInvocationAllowed(true)
|
|
||||||
.setConfigurationActivity(null) // No further settings
|
.setConfigurationActivity(null) // No further settings
|
||||||
.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
|
.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Regardless of its contents, non-null manualRule means that manual rule is active.
|
return ZenMode.manualDndMode(manualDndRule, config != null && config.isManualActive());
|
||||||
return ZenMode.manualDndMode(manualDndRule,
|
|
||||||
config != null && config.manualRule != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isRuleActive(String id, ZenModeConfig config) {
|
private static boolean isRuleActive(String id, ZenModeConfig config) {
|
||||||
@@ -191,10 +186,16 @@ class ZenModesBackend {
|
|||||||
|
|
||||||
void updateMode(ZenMode mode) {
|
void updateMode(ZenMode mode) {
|
||||||
if (mode.isManualDnd()) {
|
if (mode.isManualDnd()) {
|
||||||
NotificationManager.Policy dndPolicy =
|
try {
|
||||||
new ZenModeConfig().toNotificationPolicy(requireNonNull(mode.getPolicy()));
|
NotificationManager.Policy dndPolicy =
|
||||||
mNotificationManager.setNotificationPolicy(dndPolicy, /* fromUser= */ true);
|
new ZenModeConfig().toNotificationPolicy(mode.getPolicy());
|
||||||
// TODO: b/333530553 - Update ZenDeviceEffects of the manual DND too.
|
mNotificationManager.setNotificationPolicy(dndPolicy, /* fromUser= */ true);
|
||||||
|
|
||||||
|
mNotificationManager.setManualZenRuleDeviceEffects(
|
||||||
|
mode.getRule().getDeviceEffects());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Error updating manual mode", e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mNotificationManager.updateAutomaticZenRule(mode.getId(), mode.getRule(),
|
mNotificationManager.updateAutomaticZenRule(mode.getId(), mode.getRule(),
|
||||||
/* fromUser= */ true);
|
/* fromUser= */ true);
|
||||||
|
@@ -400,7 +400,7 @@ public class ZenModeBackend {
|
|||||||
ZenPolicy setDefaultZenPolicy(ZenPolicy zenPolicy) {
|
ZenPolicy setDefaultZenPolicy(ZenPolicy zenPolicy) {
|
||||||
int calls;
|
int calls;
|
||||||
if (mPolicy.allowCalls()) {
|
if (mPolicy.allowCalls()) {
|
||||||
calls = ZenAdapters.notificationPolicySendersToZenPolicyPeopleType(
|
calls = ZenAdapters.prioritySendersToPeopleType(
|
||||||
mPolicy.allowCallsFrom());
|
mPolicy.allowCallsFrom());
|
||||||
} else {
|
} else {
|
||||||
calls = ZenPolicy.PEOPLE_TYPE_NONE;
|
calls = ZenPolicy.PEOPLE_TYPE_NONE;
|
||||||
@@ -408,7 +408,7 @@ public class ZenModeBackend {
|
|||||||
|
|
||||||
int messages;
|
int messages;
|
||||||
if (mPolicy.allowMessages()) {
|
if (mPolicy.allowMessages()) {
|
||||||
messages = ZenAdapters.notificationPolicySendersToZenPolicyPeopleType(
|
messages = ZenAdapters.prioritySendersToPeopleType(
|
||||||
mPolicy.allowMessagesFrom());
|
mPolicy.allowMessagesFrom());
|
||||||
} else {
|
} else {
|
||||||
messages = ZenPolicy.PEOPLE_TYPE_NONE;
|
messages = ZenPolicy.PEOPLE_TYPE_NONE;
|
||||||
|
@@ -102,6 +102,7 @@ android_robolectric_test {
|
|||||||
"notification_flags_lib",
|
"notification_flags_lib",
|
||||||
"platform-test-annotations",
|
"platform-test-annotations",
|
||||||
"testables",
|
"testables",
|
||||||
|
"android.app.flags-aconfig-java",
|
||||||
],
|
],
|
||||||
|
|
||||||
libs: [
|
libs: [
|
||||||
|
@@ -31,7 +31,6 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||||
import com.android.settings.testutils.shadow.ShadowNotificationManager;
|
import com.android.settings.testutils.shadow.ShadowNotificationManager;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -92,35 +91,18 @@ public class DndConditionalCardControllerTest {
|
|||||||
|
|
||||||
private ZenModeConfig getCustomConfig() {
|
private ZenModeConfig getCustomConfig() {
|
||||||
final ZenModeConfig config = new ZenModeConfig();
|
final ZenModeConfig config = new ZenModeConfig();
|
||||||
// Some sounds allowed
|
config.applyNotificationPolicy(new NotificationManager.Policy(
|
||||||
config.allowAlarms = true;
|
NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
|
||||||
config.allowMedia = false;
|
| NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS
|
||||||
config.allowSystem = false;
|
| NotificationManager.Policy.PRIORITY_CATEGORY_CALLS,
|
||||||
config.allowCalls = true;
|
NotificationManager.Policy.PRIORITY_SENDERS_ANY, 0));
|
||||||
config.allowRepeatCallers = true;
|
|
||||||
config.allowMessages = false;
|
|
||||||
config.allowReminders = false;
|
|
||||||
config.allowEvents = false;
|
|
||||||
config.areChannelsBypassingDnd = false;
|
|
||||||
config.allowCallsFrom = ZenModeConfig.SOURCE_ANYONE;
|
|
||||||
config.allowMessagesFrom = ZenModeConfig.SOURCE_ANYONE;
|
|
||||||
config.suppressedVisualEffects = 0;
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZenModeConfig getMutedAllConfig() {
|
private ZenModeConfig getMutedAllConfig() {
|
||||||
final ZenModeConfig config = new ZenModeConfig();
|
final ZenModeConfig config = new ZenModeConfig();
|
||||||
// No sounds allowed
|
config.applyNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
|
||||||
config.allowAlarms = false;
|
|
||||||
config.allowMedia = false;
|
|
||||||
config.allowSystem = false;
|
|
||||||
config.allowCalls = false;
|
|
||||||
config.allowRepeatCallers = false;
|
|
||||||
config.allowMessages = false;
|
|
||||||
config.allowReminders = false;
|
|
||||||
config.allowEvents = false;
|
|
||||||
config.areChannelsBypassingDnd = false;
|
config.areChannelsBypassingDnd = false;
|
||||||
config.suppressedVisualEffects = 0;
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,12 @@
|
|||||||
package com.android.settings.notification.modes;
|
package com.android.settings.notification.modes;
|
||||||
|
|
||||||
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||||||
|
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
|
||||||
|
import static android.provider.Settings.Global.ZEN_MODE_OFF;
|
||||||
|
import static android.service.notification.Condition.SOURCE_UNKNOWN;
|
||||||
|
import static android.service.notification.Condition.STATE_FALSE;
|
||||||
|
import static android.service.notification.Condition.STATE_TRUE;
|
||||||
|
import static android.service.notification.ZenPolicy.STATE_ALLOW;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
@@ -27,13 +33,17 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.AutomaticZenRule;
|
import android.app.AutomaticZenRule;
|
||||||
|
import android.app.Flags;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.NotificationManager.Policy;
|
import android.app.NotificationManager.Policy;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.platform.test.annotations.EnableFlags;
|
||||||
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.notification.Condition;
|
import android.service.notification.Condition;
|
||||||
import android.service.notification.ZenAdapters;
|
import android.service.notification.ZenAdapters;
|
||||||
|
import android.service.notification.ZenDeviceEffects;
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
import android.service.notification.ZenPolicy;
|
import android.service.notification.ZenPolicy;
|
||||||
|
|
||||||
@@ -42,6 +52,7 @@ import com.android.settings.R;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@@ -54,6 +65,7 @@ import java.time.Duration;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||||
public class ZenModesBackendTest {
|
public class ZenModesBackendTest {
|
||||||
|
|
||||||
private static final String ZEN_RULE_ID = "rule";
|
private static final String ZEN_RULE_ID = "rule";
|
||||||
@@ -76,13 +88,22 @@ public class ZenModesBackendTest {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ZenModesBackend mBackend;
|
private ZenModesBackend mBackend;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
|
||||||
|
SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
|
||||||
|
|
||||||
// Helper methods to add active/inactive rule state to a config. Returns a copy.
|
// Helper methods to add active/inactive rule state to a config. Returns a copy.
|
||||||
private ZenModeConfig configWithManualRule(ZenModeConfig base, boolean active) {
|
private ZenModeConfig configWithManualRule(ZenModeConfig base, boolean active) {
|
||||||
ZenModeConfig out = base.copy();
|
ZenModeConfig out = base.copy();
|
||||||
if (!active) {
|
|
||||||
out.manualRule = null;
|
if (active) {
|
||||||
|
out.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
|
||||||
|
out.manualRule.condition =
|
||||||
|
new Condition(out.manualRule.conditionId, "", STATE_TRUE, SOURCE_UNKNOWN);
|
||||||
} else {
|
} else {
|
||||||
out.manualRule = new ZenModeConfig.ZenRule();
|
out.manualRule.zenMode = ZEN_MODE_OFF;
|
||||||
|
out.manualRule.condition =
|
||||||
|
new Condition(out.manualRule.conditionId, "", STATE_FALSE, SOURCE_UNKNOWN);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -130,7 +151,10 @@ public class ZenModesBackendTest {
|
|||||||
Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS);
|
Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS);
|
||||||
when(mNm.getAutomaticZenRules()).thenReturn(
|
when(mNm.getAutomaticZenRules()).thenReturn(
|
||||||
ImmutableMap.of("rule1", ZEN_RULE, "rule2", rule2));
|
ImmutableMap.of("rule1", ZEN_RULE, "rule2", rule2));
|
||||||
when(mNm.getNotificationPolicy()).thenReturn(dndPolicy);
|
ZenModeConfig config = new ZenModeConfig();
|
||||||
|
config.applyNotificationPolicy(dndPolicy);
|
||||||
|
assertThat(config.manualRule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_ALLOW);
|
||||||
|
when(mNm.getZenModeConfig()).thenReturn(config);
|
||||||
|
|
||||||
List<ZenMode> modes = mBackend.getModes();
|
List<ZenMode> modes = mBackend.getModes();
|
||||||
|
|
||||||
@@ -154,7 +178,9 @@ public class ZenModesBackendTest {
|
|||||||
public void getMode_manualDnd_returnsMode() {
|
public void getMode_manualDnd_returnsMode() {
|
||||||
Policy dndPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS,
|
Policy dndPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS,
|
||||||
Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS);
|
Policy.PRIORITY_SENDERS_CONTACTS, Policy.PRIORITY_SENDERS_CONTACTS);
|
||||||
when(mNm.getNotificationPolicy()).thenReturn(dndPolicy);
|
ZenModeConfig config = new ZenModeConfig();
|
||||||
|
config.applyNotificationPolicy(dndPolicy);
|
||||||
|
when(mNm.getZenModeConfig()).thenReturn(config);
|
||||||
|
|
||||||
ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
|
ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
|
||||||
|
|
||||||
@@ -193,11 +219,11 @@ public class ZenModesBackendTest {
|
|||||||
// Set up a base config with an active rule to make sure we're looking at the correct info
|
// Set up a base config with an active rule to make sure we're looking at the correct info
|
||||||
ZenModeConfig configWithActiveRule = configWithRule(new ZenModeConfig(), ZEN_RULE_ID,
|
ZenModeConfig configWithActiveRule = configWithRule(new ZenModeConfig(), ZEN_RULE_ID,
|
||||||
ZEN_RULE, true);
|
ZEN_RULE, true);
|
||||||
when(mNm.getZenModeConfig()).thenReturn(configWithActiveRule);
|
|
||||||
|
|
||||||
// Equivalent to disallowAllSounds()
|
// Equivalent to disallowAllSounds()
|
||||||
Policy dndPolicy = new Policy(0, 0, 0);
|
Policy dndPolicy = new Policy(0, 0, 0);
|
||||||
when(mNm.getNotificationPolicy()).thenReturn(dndPolicy);
|
configWithActiveRule.applyNotificationPolicy(dndPolicy);
|
||||||
|
when(mNm.getZenModeConfig()).thenReturn(configWithActiveRule);
|
||||||
|
|
||||||
ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
|
ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID);
|
||||||
|
|
||||||
@@ -232,6 +258,23 @@ public class ZenModesBackendTest {
|
|||||||
assertThat(activeMode.isActive()).isTrue();
|
assertThat(activeMode.isActive()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateMode_manualDnd_setsDeviceEffects() throws Exception {
|
||||||
|
ZenMode manualDnd = ZenMode.manualDndMode(
|
||||||
|
new AutomaticZenRule.Builder("DND", Uri.EMPTY)
|
||||||
|
.setZenPolicy(new ZenPolicy())
|
||||||
|
.setDeviceEffects(new ZenDeviceEffects.Builder()
|
||||||
|
.setShouldDimWallpaper(true)
|
||||||
|
.build())
|
||||||
|
.build(), false);
|
||||||
|
|
||||||
|
mBackend.updateMode(manualDnd);
|
||||||
|
|
||||||
|
verify(mNm).setManualZenRuleDeviceEffects(new ZenDeviceEffects.Builder()
|
||||||
|
.setShouldDimWallpaper(true)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateMode_manualDnd_setsNotificationPolicy() {
|
public void updateMode_manualDnd_setsNotificationPolicy() {
|
||||||
ZenMode manualDnd = ZenMode.manualDndMode(
|
ZenMode manualDnd = ZenMode.manualDndMode(
|
||||||
@@ -293,7 +336,7 @@ public class ZenModesBackendTest {
|
|||||||
public void deactivateMode_manualDnd_setsZenModeOff() {
|
public void deactivateMode_manualDnd_setsZenModeOff() {
|
||||||
mBackend.deactivateMode(ZenMode.manualDndMode(MANUAL_DND_RULE, true));
|
mBackend.deactivateMode(ZenMode.manualDndMode(MANUAL_DND_RULE, true));
|
||||||
|
|
||||||
verify(mNm).setZenMode(eq(Settings.Global.ZEN_MODE_OFF), eq(null), any(), eq(true));
|
verify(mNm).setZenMode(eq(ZEN_MODE_OFF), eq(null), any(), eq(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user