Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31d5fbff authored by Matías Hernández's avatar Matías Hernández Committed by Android (Google) Code Review
Browse files

Merge "Update Priority Modes segment summary" into main

parents 3695ff47 f0952bef
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -7984,6 +7984,26 @@
    <!-- Priority Modes: Option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=40] -->
    <string name="zen_mode_select_schedule_calendar">Calendar events</string>
    <!-- Priority Modes: Summary for the modes segment, when at least one mode is active. [CHAR LIMIT=NONE]-->
    <string name="zen_modes_summary_some_active">
        {count, plural, offset:2
            =0    {}
            =1    {{mode_1} is active}
            =2    {{mode_1} and {mode_2} are active}
            =3    {{mode_1}, {mode_2}, and {mode_3} are active}
            other {{mode_1}, {mode_2}, and # more are active}
        }
    </string>
    <!-- Priority Modes: Summary for the modes segment, when no modes are active. [CHAR LIMIT=NONE]-->
    <string name="zen_modes_summary_none_active">
        {count, plural,
            =0    {}
            =1    {1 mode can turn on automatically}
            other {# modes can turn on automatically}
        }
    </string>
    <!-- Priority Modes: Short text that indicates that a mode is currently on (active). [CHAR_LIMIT=10] -->
    <string name="zen_mode_active_text">ON</string>
+24 −23
Original line number Diff line number Diff line
@@ -42,13 +42,10 @@ import static android.service.notification.ZenPolicy.VISUAL_EFFECT_STATUS_BAR;

import android.content.Context;
import android.icu.text.MessageFormat;
import android.provider.Settings;
import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy;
import android.service.notification.ZenPolicy.ConversationSenders;
import android.service.notification.ZenPolicy.PeopleType;
import android.util.ArrayMap;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -496,32 +493,36 @@ class ZenModeSummaryHelper {
        return msgFormat.format(args);
    }

    String getSoundSummary(int zenMode, ZenModeConfig config) {
        if (zenMode != Settings.Global.ZEN_MODE_OFF) {
            String description = ZenModeConfig.getDescription(mContext, true, config, false);
    String getModesSummary(List<ZenMode> modes) {
        List<ZenMode> activeModes = modes.stream().filter(ZenMode::isActive).toList();

            if (description == null) {
                return mContext.getString(R.string.zen_mode_sound_summary_on);
            } else {
                return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
                        description);
            }
        } else {
            int count = 0;
            final ArrayMap<String, ZenModeConfig.ZenRule> ruleMap = config.automaticRules;
            if (ruleMap != null) {
                for (ZenModeConfig.ZenRule rule : ruleMap.values()) {
                    if (rule != null && rule.enabled) {
                        count++;
                    }
        if (!activeModes.isEmpty()) {
            MessageFormat msgFormat = new MessageFormat(
                    mContext.getString(R.string.zen_modes_summary_some_active),
                    Locale.getDefault());

            Map<String, Object> args = new HashMap<>();
            args.put("count", activeModes.size());
            args.put("mode_1", activeModes.get(0).getName());
            if (activeModes.size() >= 2) {
                args.put("mode_2", activeModes.get(1).getName());
                if (activeModes.size() == 3) {
                    args.put("mode_3", activeModes.get(2).getName());
                }
            }

            return msgFormat.format(args);
        } else {
            int automaticModeCount = (int) modes.stream()
                    .filter(m -> !m.isManualDnd() && !m.isCustomManual())
                    .count();

            MessageFormat msgFormat = new MessageFormat(
                    mContext.getString(R.string.modes_sound_summary_off),
                    mContext.getString(R.string.zen_modes_summary_none_active),
                    Locale.getDefault());
            Map<String, Object> msgArgs = new HashMap<>();
            msgArgs.put("count", count);
            Map<String, Object> msgArgs = Map.of("count", automaticModeCount);
            return msgFormat.format(msgArgs);
        }
    }

}
+22 −59
Original line number Diff line number Diff line
@@ -17,35 +17,31 @@
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;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.notification.modes.ZenModesBackend;

public class ZenModesLinkPreferenceController extends BasePreferenceController
        implements LifecycleObserver, OnResume, OnPause {
        implements LifecycleObserver, OnStart, OnStop {

    private SettingObserver mSettingObserver;
    private ZenModeSummaryHelper mSummaryBuilder;
    private NotificationManager mNm;
    private final ZenModesBackend mBackend;
    private final ZenSettingsObserver mSettingObserver;
    private final ZenModeSummaryHelper mSummaryBuilder;

    private Preference mPreference;

    public ZenModesLinkPreferenceController(Context context, String key) {
        super(context, key);
        mBackend = ZenModesBackend.getInstance(context);
        mSummaryBuilder = new ZenModeSummaryHelper(context, ZenHelperBackend.getInstance(context));
        mNm = mContext.getSystemService(NotificationManager.class);
        mSettingObserver = new ZenSettingsObserver(context, this::onZenSettingsChanged);
    }

    @Override
@@ -57,64 +53,31 @@ public class ZenModesLinkPreferenceController extends BasePreferenceController
    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        Preference preference = screen.findPreference(getPreferenceKey());
        mSettingObserver = new SettingObserver(preference);
        mPreference = screen.findPreference(getPreferenceKey());
    }

    @Override
    public void onResume() {
    public void onStart() {
        if (mSettingObserver != null) {
            mSettingObserver.register(mContext.getContentResolver());
            mSettingObserver.register();
        }
    }

    @Override
    public void onPause() {
        if (mSettingObserver != null) {
            mSettingObserver.unregister(mContext.getContentResolver());
    private void onZenSettingsChanged() {
        if (mPreference != null) {
            updateState(mPreference);
        }
    }

    @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);
        preference.setSummary(mSummaryBuilder.getModesSummary(mBackend.getModes()));
    }

    @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);
            }
    public void onStop() {
        if (mSettingObserver != null) {
            mSettingObserver.unregister();
        }
    }
}
+65 −68
Original line number Diff line number Diff line
@@ -16,10 +16,6 @@

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.CONVERSATION_SENDERS_IMPORTANT;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
@@ -33,17 +29,16 @@ import static com.google.common.truth.Truth.assertThat;

import static org.robolectric.Shadows.shadowOf;

import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.Condition;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy;
@@ -65,6 +60,7 @@ import org.robolectric.RuntimeEnvironment;
import java.util.Random;

@RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI)
public class ZenModesSummaryHelperTest {
    private static final int WORK_PROFILE_ID = 3;

@@ -480,85 +476,86 @@ public class ZenModesSummaryHelperTest {
    }

    @Test
    @EnableFlags(Flags.FLAG_MODES_UI)
    public void getSoundSummary_off_noRules() {
        ZenModeConfig config = new ZenModeConfig();
    public void getModesSummary_noRules_noSummary() {
        String summary = mSummaryHelper.getModesSummary(ImmutableList.of());
        assertThat(summary).isEmpty();
    }

        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)).isEqualTo("Off");
    @Test
    public void getModesSummary_onlyDndAndNotActive_noSummary() {
        ImmutableList<ZenMode> modes = ImmutableList.of(TestModeBuilder.MANUAL_DND_INACTIVE);
        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEmpty();
    }

    @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);
    public void getModesSummary_noRulesActive_countsOnlyAutomaticModes() {
        ImmutableList<ZenMode> modes = ImmutableList.of(
                TestModeBuilder.MANUAL_DND_INACTIVE, // Not automatic
                new TestModeBuilder().setName("Auto 1").build(), // App provided automatic
                new TestModeBuilder()
                        .setName("Custom manual 1")
                        .setPackage(SystemZenRules.PACKAGE_ANDROID)
                        .setType(AutomaticZenRule.TYPE_OTHER)
                        .setConditionId(ZenModeConfig.toCustomManualConditionId())
                        .build(), // Custom manual, not automatic
                new TestModeBuilder()
                        .setName("Sleep")
                        .setPackage(SystemZenRules.PACKAGE_ANDROID)
                        .setType(AutomaticZenRule.TYPE_SCHEDULE_TIME)
                        .build() // Time based, automatic.
        );

        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config))
                .isEqualTo("Off / 1 mode can turn on automatically");
        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEqualTo("2 modes 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);
    public void getModesSummary_oneModeActive_listsMode() {
        ImmutableList<ZenMode> modes = ImmutableList.of(
                TestModeBuilder.MANUAL_DND_ACTIVE,
                new TestModeBuilder().setName("Inactive").setActive(false).build());

        assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config))
                .isEqualTo("Off / 2 modes can turn on automatically");
        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEqualTo("Do Not Disturb is active");
    }

    @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");
    public void getModesSummary_twoModesActive_listsModes() {
        ImmutableList<ZenMode> modes = ImmutableList.of(
                TestModeBuilder.MANUAL_DND_ACTIVE,
                new TestModeBuilder().setName("Inactive").setActive(false).build(),
                new TestModeBuilder().setName("Active #1").setActive(true).build());

        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEqualTo("Do Not Disturb and Active #1 are active");
    }

    @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 /");
    public void getModesSummary_threeModesActive_listsModes() {
        ImmutableList<ZenMode> modes = ImmutableList.of(
                TestModeBuilder.MANUAL_DND_INACTIVE,
                new TestModeBuilder().setName("Inactive #1").setActive(false).build(),
                new TestModeBuilder().setName("Active #1").setActive(true).build(),
                new TestModeBuilder().setName("Active #2").setActive(true).build(),
                new TestModeBuilder().setName("Inactive #2").setActive(false).build(),
                new TestModeBuilder().setName("Active #3").setActive(true).build());

        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEqualTo("Active #1, Active #2, and Active #3 are active");
    }

    @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 /");
    public void getModesSummary_manyModesActive_listsACouple() {
        ImmutableList<ZenMode> modes = ImmutableList.of(
                TestModeBuilder.MANUAL_DND_ACTIVE,
                new TestModeBuilder().setName("Inactive #1").setActive(false).build(),
                new TestModeBuilder().setName("Active #1").setActive(true).build(),
                new TestModeBuilder().setName("Active #2").setActive(true).build(),
                new TestModeBuilder().setName("Inactive #2").setActive(false).build(),
                new TestModeBuilder().setName("Active #3").setActive(true).build());

        String summary = mSummaryHelper.getModesSummary(modes);
        assertThat(summary).isEqualTo("Do Not Disturb, Active #1, and 2 more are active");
    }
}