Merge "Support device effects for manual mode" into main

This commit is contained in:
Julia Reynolds
2024-06-12 23:29:59 +00:00
committed by Android (Google) Code Review
6 changed files with 81 additions and 54 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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: [

View File

@@ -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;
} }
} }

View File

@@ -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