From 4fd34aa3861c7c2c75e70aa59d0ad1c1f854aed9 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 3 Jul 2024 16:19:18 -0400 Subject: [PATCH] Create a new link preference for priority modes entry Test: ZenModesSummaryHelperTest Test: manual. Successfully search for both 'event' and 'priority' Flag: android.app.modes_ui Bug: 341726633 Change-Id: Ib7bd1a5c2f7b06b1728a66f7a9cef53cd45acc0b --- res/values/strings.xml | 8 ++ res/xml/configure_notification_settings.xml | 9 ++ .../modes/ZenModeSummaryHelper.java | 32 +++++ .../ZenModesLinkPreferenceController.java | 120 ++++++++++++++++++ .../zen/ZenModePreferenceController.java | 16 +-- .../modes/ZenModesSummaryHelperTest.java | 99 +++++++++++++++ 6 files changed, 269 insertions(+), 15 deletions(-) create mode 100644 src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 40b160a3915..29cbc9011e0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8118,6 +8118,14 @@ Additional actions + + + {count, plural, + =0 {Off} + =1 {Off / 1 mode can turn on automatically} + other {Off / # modes can turn on automatically} + } + Display settings diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index b673a0839b0..1e5b241ea82 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -135,6 +135,15 @@ settings:controller="com.android.settings.notification.zen.ZenModePreferenceController" /> + + ruleMap = config.automaticRules; + if (ruleMap != null) { + for (ZenModeConfig.ZenRule rule : ruleMap.values()) { + if (rule != null && rule.enabled) { + count++; + } + } + } + MessageFormat msgFormat = new MessageFormat( + mContext.getString(R.string.modes_sound_summary_off), + Locale.getDefault()); + Map msgArgs = new HashMap<>(); + msgArgs.put("count", count); + return msgFormat.format(msgArgs); + } + } } diff --git a/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java new file mode 100644 index 00000000000..f2679d7d0d0 --- /dev/null +++ b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2024 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.modes; + +import android.app.Flags; +import android.app.NotificationManager; +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.UserHandle; +import android.provider.Settings; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnPause; +import com.android.settingslib.core.lifecycle.events.OnResume; + +public class ZenModesLinkPreferenceController extends BasePreferenceController + implements LifecycleObserver, OnResume, OnPause { + + private SettingObserver mSettingObserver; + private ZenModeSummaryHelper mSummaryBuilder; + private NotificationManager mNm; + + public ZenModesLinkPreferenceController(Context context, String key) { + super(context, key); + mSummaryBuilder = new ZenModeSummaryHelper(context, ZenHelperBackend.getInstance(context)); + mNm = mContext.getSystemService(NotificationManager.class); + } + + @Override + @AvailabilityStatus + public int getAvailabilityStatus() { + return Flags.modesUi() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + Preference preference = screen.findPreference(getPreferenceKey()); + mSettingObserver = new SettingObserver(preference); + } + + @Override + public void onResume() { + if (mSettingObserver != null) { + mSettingObserver.register(mContext.getContentResolver()); + } + } + + @Override + public void onPause() { + if (mSettingObserver != null) { + mSettingObserver.unregister(mContext.getContentResolver()); + } + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(mSummaryBuilder.getSoundSummary( + Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.ZEN_MODE, + Settings.Global.ZEN_MODE_OFF), + mNm.getZenModeConfig())); + } + + class SettingObserver extends ContentObserver { + private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE); + private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor( + Settings.Global.ZEN_MODE_CONFIG_ETAG); + + private final Preference mPreference; + + public SettingObserver(Preference preference) { + super(new Handler()); + mPreference = preference; + } + + public void register(ContentResolver cr) { + cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL); + cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL); + } + + public void unregister(ContentResolver cr) { + cr.unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (ZEN_MODE_URI.equals(uri)) { + updateState(mPreference); + } + + if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) { + updateState(mPreference); + } + } + } +} diff --git a/src/com/android/settings/notification/zen/ZenModePreferenceController.java b/src/com/android/settings/notification/zen/ZenModePreferenceController.java index 7c36d80f8ad..c21bc3bc260 100644 --- a/src/com/android/settings/notification/zen/ZenModePreferenceController.java +++ b/src/com/android/settings/notification/zen/ZenModePreferenceController.java @@ -28,9 +28,7 @@ import android.provider.Settings; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.settings.R; import com.android.settings.core.BasePreferenceController; -import com.android.settings.notification.modes.ZenModesListFragment; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; @@ -51,7 +49,6 @@ public class ZenModePreferenceController extends BasePreferenceController super.displayPreference(screen); Preference preference = screen.findPreference(getPreferenceKey()); mSettingObserver = new SettingObserver(preference); - maybeSetTitleAndDestination(preference); } @Override @@ -70,28 +67,17 @@ public class ZenModePreferenceController extends BasePreferenceController @Override public int getAvailabilityStatus() { - return AVAILABLE_UNSEARCHABLE; + return Flags.modesUi() ? UNSUPPORTED_ON_DEVICE : AVAILABLE_UNSEARCHABLE; } @Override public void updateState(Preference preference) { super.updateState(preference); - maybeSetTitleAndDestination(preference); if (preference.isEnabled()) { preference.setSummary(mSummaryBuilder.getSoundSummary()); } } - // Only when modes_ui is active: change title & target fragment. - private void maybeSetTitleAndDestination(Preference preference) { - if (!Flags.modesUi()) { - return; - } - - preference.setTitle(R.string.zen_modes_list_title); - preference.setFragment(ZenModesListFragment.class.getCanonicalName()); - } - class SettingObserver extends ContentObserver { private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE); private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor( diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java index 62b5ee02ee6..308650fe8c9 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java @@ -16,6 +16,10 @@ package com.android.settings.notification.modes; +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_TRUE; import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS; @@ -24,13 +28,21 @@ import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS; import static com.google.common.truth.Truth.assertThat; +import android.app.Flags; +import android.content.ComponentName; import android.content.Context; +import android.net.Uri; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.service.notification.Condition; import android.service.notification.ZenDeviceEffects; +import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; import com.android.settingslib.notification.modes.ZenMode; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; @@ -46,6 +58,10 @@ public class ZenModesSummaryHelperTest { private ZenModeSummaryHelper mSummaryHelper; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule( + SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT); + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -351,4 +367,87 @@ public class ZenModesSummaryHelperTest { assertThat(mSummaryHelper.getAppsSummary(zenMode, apps)).isEqualTo("FifthApp, FourthApp, " + "and 4 more can interrupt"); } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_noRules() { + ZenModeConfig config = new ZenModeConfig(); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)).isEqualTo("Off"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_oneRule() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.enabled = true; + config.automaticRules.put("key", rule); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)) + .isEqualTo("Off / 1 mode can turn on automatically"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_twoRules() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.enabled = true; + ZenModeConfig.ZenRule rule2 = new ZenModeConfig.ZenRule(); + rule2.enabled = true; + config.automaticRules.put("key", rule); + config.automaticRules.put("key2", rule2); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)) + .isEqualTo("Off / 2 modes can turn on automatically"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_noDescription() { + ZenModeConfig config = new ZenModeConfig(); + config.manualRule.conditionId = Uri.EMPTY; + config.manualRule.pkg = "android"; + config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN); + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .isEqualTo("On"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_manualDescription() { + ZenModeConfig config = new ZenModeConfig(); + config.manualRule.conditionId = ZenModeConfig.toCountdownConditionId( + System.currentTimeMillis() + 10000, false); + config.manualRule.pkg = "android"; + config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN); + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .startsWith("On /"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_automatic() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.configurationActivity = new ComponentName("a", "a"); + rule.component = new ComponentName("b", "b"); + rule.conditionId = new Uri.Builder().scheme("hello").build(); + rule.condition = new Condition(rule.conditionId, "", STATE_TRUE); + rule.enabled = true; + rule.creationTime = 123; + rule.id = "id"; + rule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + rule.modified = true; + rule.name = "name"; + rule.snoozing = false; + rule.pkg = "b"; + config.automaticRules.put("key", rule); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .startsWith("On /"); + } }