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

Commit bf6d9580 authored by Yining Liu's avatar Yining Liu
Browse files

Update Settings Page for Avalanche Suppression

Update the Settings Page for the Avalanche
visual and auditory Suppression.

Bug: 330606963
Test: PoliteNotificationPreferenceControllerTest
Flag: com.android.server.notification.polite_notifications
Change-Id: I60b64a0c00cafb22ac1db74285002862affb82d2
parent a848c576
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -8680,7 +8680,9 @@
    <string name="notif_listener_more_settings_desc">More settings are available inside this app</string>
    <!-- Title for Polite Notifications setting  [CHAR LIMIT=30]-->
    <string name="notification_polite_title">Notification cooldown</string>
    <string name="notification_polite_title">Cooldown</string>
    <string name="notification_polite_main_control_title">Use Cooldown</string>
    <string name="notification_polite_description">When you get many notifications within a short time span, your device will minimize sound interruptions and pop-ups on the screen. Calls, alarms, and priority conversations will still alert as notmal, and all delivered notifications are easy to find in the Shade.</string>
    <string name="notification_polite_all_apps">Apply cooldown to all notifications</string>
    <string name="notification_polite_all_apps_summary">Gradually lower the notification volume when you get many successive notifications from the same app</string>
    <string name="notification_polite_conversations">Apply cooldown to conversations</string>
@@ -8690,7 +8692,7 @@
    <string name="notification_polite_vibrate_unlocked">Vibrate when unlocked</string>
    <string name="notification_polite_vibrate_unlocked_summary">Only vibrate when screen is unlocked</string>
    <string name="notification_polite_work">Apply to work profiles</string>
    <string name="notification_polite_work_summary">Apply the notification cooldown settings from your personal profile to your work profile</string>
    <string name="notification_polite_work_summary">Apply to work profile apps</string>
    <!-- Title for managing VR (virtual reality) helper services. [CHAR LIMIT=50] -->
+33 −14
Original line number Diff line number Diff line
@@ -17,22 +17,41 @@

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:title="@string/notification_polite_title">

    <com.android.settings.RestrictedListPreference
        android:key="polite_notifications_pref_dlg"
        android:persistent="false"
        android:title="@string/notification_polite_title"
        android:entries="@array/notification_polite_options"
        android:entryValues="@array/notification_polite_options_values"
        settings:controller="com.android.settings.notification.PoliteNotificationFilterController"/>

    <SwitchPreferenceCompat
        android:key="notification_polite_vibrate_unlocked"
        android:persistent="false"
        android:title="@string/notification_polite_vibrate_unlocked"
        android:summary="@string/notification_polite_vibrate_unlocked_summary"
        settings:controller="com.android.settings.notification.PoliteNotifVibrateUnlockedToggleController" />
<!--    <com.android.settings.RestrictedListPreference-->
<!--        android:key="polite_notifications_pref_dlg"-->
<!--        android:persistent="false"-->
<!--        android:title="@string/notification_polite_title"-->
<!--        android:entries="@array/notification_polite_options"-->
<!--        android:entryValues="@array/notification_polite_options_values"-->
<!--        settings:controller="com.android.settings.notification.PoliteNotificationFilterController"/>-->

<!--    <SwitchPreferenceCompat-->
<!--        android:key="notification_polite_vibrate_unlocked"-->
<!--        android:persistent="false"-->
<!--        android:title="@string/notification_polite_vibrate_unlocked"-->
<!--        android:summary="@string/notification_polite_vibrate_unlocked_summary"-->
<!--        settings:controller="com.android.settings.notification.PoliteNotifVibrateUnlockedToggleController" />-->

    <com.android.settingslib.widget.TopIntroPreference
        android:key="polite_notification_desc"
        android:title="@string/notification_polite_description"/>

<!--    TODO(b/330606963): add the illustration back when animation is ready-->
<!--    <com.android.settingslib.widget.IllustrationPreference-->
<!--        android:key="bubbles_illustration"-->
<!--        settings:searchable="false"-->
<!--        android:selectable="false"-->
<!--        app:lottie_rawRes="@raw/lottie_bubbles"-->
<!--        app:lottie_cacheComposition="false"-->
<!--        settings:dynamicColor="true" />-->

    <com.android.settingslib.widget.MainSwitchPreference
        android:key="polite_notification_global_pref"
        android:title="@string/notification_polite_main_control_title"
        settings:controller="com.android.settings.notification.PoliteNotificationGlobalPreferenceController" />

    <SwitchPreferenceCompat
        android:key="notification_polite_work_profile"
+67 −6
Original line number Diff line number Diff line
@@ -16,29 +16,52 @@

package com.android.settings.notification;

import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.android.settings.notification.PoliteNotificationGlobalPreferenceController.ON;
import static com.android.settings.notification.PoliteNotificationGlobalPreferenceController.OFF;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.server.notification.Flags;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;

/**
 * Controls the toggle that determines whether notification cooldown
 * should apply to work profiles.
 */
public class PoliteNotifWorkProfileToggleController extends TogglePreferenceController {
public class PoliteNotifWorkProfileToggleController extends TogglePreferenceController implements
        LifecycleEventObserver {

    private final int mManagedProfileId;
    private Preference mPreference;
    private final ContentResolver mContentResolver;

    public PoliteNotifWorkProfileToggleController(Context context, String preferenceKey) {
    final ContentObserver mContentObserver = new ContentObserver(
            new Handler(Looper.getMainLooper())) {
        @Override
        public void onChange(boolean selfChange, @Nullable Uri uri) {
            updateState(mPreference);
        }
    };

    public PoliteNotifWorkProfileToggleController(@NonNull Context context,
            @NonNull String preferenceKey) {
        this(context, preferenceKey, new AudioHelper(context));
    }

@@ -47,6 +70,25 @@ public class PoliteNotifWorkProfileToggleController extends TogglePreferenceCont
                AudioHelper helper) {
        super(context, preferenceKey);
        mManagedProfileId = helper.getManagedProfileId(UserManager.get(mContext));
        mContentResolver = context.getContentResolver();
    }

    @Override
    public void displayPreference(@NonNull PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner,
            @NonNull Lifecycle.Event event) {
        if (event == Lifecycle.Event.ON_RESUME) {
            mContentResolver.registerContentObserver(
                    Settings.System.getUriFor(Settings.System.NOTIFICATION_COOLDOWN_ENABLED),
                    /* notifyForDescendants= */ false, mContentObserver);
        } else if (event == Lifecycle.Event.ON_PAUSE) {
            mContentResolver.unregisterContentObserver(mContentObserver);
        }
    }

    @Override
@@ -56,11 +98,18 @@ public class PoliteNotifWorkProfileToggleController extends TogglePreferenceCont
            return CONDITIONALLY_UNAVAILABLE;
        }

        if (!isCoolDownEnabledForPrimary()) {
            return CONDITIONALLY_UNAVAILABLE;
        }

        return (mManagedProfileId != UserHandle.USER_NULL) ? AVAILABLE : DISABLED_FOR_USER;
    }

    @Override
    public boolean isChecked() {
        if (!isCoolDownEnabledForPrimary()) {
            return false;
        }
        return Settings.System.getIntForUser(mContext.getContentResolver(),
                Settings.System.NOTIFICATION_COOLDOWN_ENABLED, ON, mManagedProfileId) != OFF;
    }
@@ -74,6 +123,18 @@ public class PoliteNotifWorkProfileToggleController extends TogglePreferenceCont

    @Override
    public int getSliceHighlightMenuRes() {
        return R.string.menu_key_accessibility;
        // not needed since it's not sliceable
        return NO_RES;
    }

    @Override
    public void updateState(@Nullable Preference preference) {
        if (preference == null) return;
        preference.setVisible(isAvailable());
    }

    private boolean isCoolDownEnabledForPrimary() {
        return Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.NOTIFICATION_COOLDOWN_ENABLED, ON) == ON;
    }
}
+63 −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;

import android.content.Context;
import android.provider.Settings;

import androidx.annotation.NonNull;

import com.android.server.notification.Flags;
import com.android.settings.widget.SettingsMainSwitchPreferenceController;

public class PoliteNotificationGlobalPreferenceController extends
        SettingsMainSwitchPreferenceController {

    public static final int ON = 1;
    public static final int OFF = 0;
    public PoliteNotificationGlobalPreferenceController(@NonNull Context context,
            @NonNull String preferenceKey) {
        super(context, preferenceKey);
    }

    @Override
    public int getAvailabilityStatus() {
        // TODO: b/291897570 - remove this when the feature flag is removed!
        if (Flags.politeNotifications()) {
            return AVAILABLE;
        }
        return CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public boolean isChecked() {
        return Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.NOTIFICATION_COOLDOWN_ENABLED, ON) == ON;
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        return Settings.System.putInt(mContext.getContentResolver(),
                Settings.System.NOTIFICATION_COOLDOWN_ENABLED, (isChecked ? ON : OFF));
    }

    @Override
    public int getSliceHighlightMenuRes() {
        // not needed since it's not sliceable
        return NO_RES;
    }
}