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

Commit 3b62c233 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Design refresh for modes that don't filter notifications

And fix a crash noticed in ZenModeAppsLinkPreferenceController

Test: atest com/android/settings/notification/modes
Fixes: 308820027
Flag: android.app.modes_ui
Change-Id: I0cfe4e10ca7ff97dac3b3b8756cc36f4d6f91ea2
parent 78a06622
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -8016,7 +8016,7 @@
    <string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
    <!-- Do not disturb: mode page section title [CHAR LIMIT=80] -->
    <string name="mode_interruption_filter_title">Notifications that can reach you</string>
    <string name="mode_interruption_filter_title">Stay focused</string>
    <!-- Do not disturb: mode page section title [CHAR LIMIT=80] -->
    <string name="mode_device_effects_title">Additional actions</string>
@@ -8060,7 +8060,10 @@
        other {{effect_1}, {effect_2}, and # more}
        }
    </string>
    <!-- Modes: setting for whether the mode should filter (silence/hide) notifications/volume streams -->
    <string name="mode_notification_filter_title">Filter interruptions</string>
    <!-- Modes: subtext when a mode is not filtering (silence/hide) notifications/volume streams -->
    <string name="mode_no_notification_filter">No interruptions are filtered</string>
    <!-- Do not disturb: restrict notifications settings title [CHAR LIMIT=80] -->
    <string name="zen_mode_restrict_notifications_title">Display options for filtered
+6 −1
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@
    <PreferenceCategory
            android:title="@string/mode_interruption_filter_title"
            android:key="modes_filters">

        <SwitchPreferenceCompat
            android:key="allow_filtering"
            android:title="@string/mode_notification_filter_title"/>

        <Preference
                android:key="zen_mode_people"
                android:title="@string/zen_category_people"/>
+62 −0
Original line number Diff line number Diff line
/*
 * 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 static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.TwoStatePreference;

import com.android.settings.R;

class InterruptionFilterPreferenceController extends AbstractZenModePreferenceController
        implements Preference.OnPreferenceChangeListener {

    public InterruptionFilterPreferenceController(Context context, String key,
            ZenModesBackend backend) {
        super(context, key, backend);
    }

    @Override
    public boolean isAvailable(ZenMode zenMode) {
        return !zenMode.isManualDnd();
    }

    @Override
    public void updateState(Preference preference, @NonNull ZenMode zenMode) {
        boolean filteringNotifications = zenMode.getRule().getInterruptionFilter()
                != INTERRUPTION_FILTER_ALL;
        ((TwoStatePreference) preference).setChecked(filteringNotifications);
        preference.setSummary(filteringNotifications ? "" :
                mContext.getResources().getString(R.string.mode_no_notification_filter));
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        final boolean filterNotifications = ((Boolean) newValue);
        return saveMode(zenMode -> {
            zenMode.getRule().setInterruptionFilter(filterNotifications
                    ? INTERRUPTION_FILTER_PRIORITY
                    : INTERRUPTION_FILTER_ALL);
            return zenMode;
        });
    }
}
+3 −46
Original line number Diff line number Diff line
@@ -59,26 +59,8 @@ class ZenMode {

    private static final String TAG = "ZenMode";

    /**
     * Additional value for the {@code @ZenPolicy.ChannelType} enumeration that indicates that all
     * channels can bypass DND when this policy is active.
     *
     * <p>This value shouldn't be used on "real" ZenPolicy objects sent to or returned from
     * {@link android.app.NotificationManager}; it's a way of representing rules with interruption
     * filter = {@link NotificationManager#INTERRUPTION_FILTER_ALL} in the UI.
     */
    public static final int CHANNEL_POLICY_ALL = -1;

    static final String MANUAL_DND_MODE_ID = "manual_dnd";

    @SuppressLint("WrongConstant")
    private static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALL =
            new ZenPolicy.Builder()
                    .allowChannels(CHANNEL_POLICY_ALL)
                    .allowAllSounds()
                    .showAllVisualEffects()
                    .build();

    // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy.
    private static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS =
            new ZenPolicy.Builder()
@@ -141,10 +123,8 @@ class ZenMode {
    public ZenPolicy getPolicy() {
        switch (mRule.getInterruptionFilter()) {
            case INTERRUPTION_FILTER_PRIORITY:
                return requireNonNull(mRule.getZenPolicy());

            case NotificationManager.INTERRUPTION_FILTER_ALL:
                return POLICY_INTERRUPTION_FILTER_ALL;
                return requireNonNull(mRule.getZenPolicy());

            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
                return POLICY_INTERRUPTION_FILTER_ALARMS;
@@ -172,31 +152,8 @@ class ZenMode {
            return;
        }

        // A policy with CHANNEL_POLICY_ALL is only a UI representation of the
        // INTERRUPTION_FILTER_ALL filter. Thus, switching to or away to this value only updates
        // the filter, discarding the rest of the supplied policy.
        if (policy.getAllowedChannels() == CHANNEL_POLICY_ALL
                && currentPolicy.getAllowedChannels() != CHANNEL_POLICY_ALL) {
            if (mIsManualDnd) {
                throw new IllegalArgumentException("Manual DND cannot have CHANNEL_POLICY_ALL");
            }
            mRule.setInterruptionFilter(INTERRUPTION_FILTER_ALL);
            // Preserve the existing policy, e.g. if the user goes PRIORITY -> ALL -> PRIORITY that
            // shouldn't discard all other policy customizations. The existing policy will be a
            // synthetic one if the rule originally had filter NONE or ALARMS_ONLY and that's fine.
            if (mRule.getZenPolicy() == null) {
                mRule.setZenPolicy(currentPolicy);
            }
            return;
        } else if (policy.getAllowedChannels() != CHANNEL_POLICY_ALL
                && currentPolicy.getAllowedChannels() == CHANNEL_POLICY_ALL) {
            mRule.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY);
            // Go back to whatever policy the rule had before, unless the rule never had one, in
            // which case we use the supplied policy (which we know has a valid allowedChannels).
            if (mRule.getZenPolicy() == null) {
                mRule.setZenPolicy(policy);
            }
            return;
        if (mRule.getInterruptionFilter() == INTERRUPTION_FILTER_ALL) {
            Log.wtf(TAG, "Able to change policy without filtering being enabled");
        }

        // If policy is customized from any of the "special" ones, make the rule PRIORITY.
+0 −4
Original line number Diff line number Diff line
@@ -37,10 +37,6 @@ public class ZenModeAppsFragment extends ZenModeFragmentBase {
                context, ZenModeAppsPreferenceController.KEY_PRIORITY, mBackend));
        controllers.add(new ZenModeAppsPreferenceController(
                context, ZenModeAppsPreferenceController.KEY_NONE, mBackend));
        // TODO: b/308819928 - The manual DND mode cannot have the ALL type;
        // unify the controllers into one and only create a preference if isManualDnd is false.
        controllers.add(new ZenModeAppsPreferenceController(
                context, ZenModeAppsPreferenceController.KEY_ALL, mBackend));
        return controllers;
    }

Loading