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

Commit 0e3f407f authored by Yuri Lin's avatar Yuri Lin Committed by Android (Google) Code Review
Browse files

Merge "Add setting for promoted (live) notifications" into main

parents 0f1c0f3c d5c0851c
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -8774,6 +8774,13 @@
    <!-- App Info > Notifications: Title for section where notifications bundles can be configured [CHAR LIMIT=80]-->
    <string name="notification_bundles">Notification bundles</string>
    <!-- App Info > Notifications: Title for section controlling whether this app may show notifications in a promoted format [CHAR LIMIT=80] -->
    <string name="live_notifications">Live notifications</string>
    <!-- App Info > Notifications: Text on the switch to enable or disable an app from showing notifications in a live/promoted format [CHAR LIMIT=50] -->
    <string name="live_notifications_switch">Show live info</string>
    <!-- App Info > Notifications: Text accompanying the "Show live info" switch explaining the purpose of the setting -->
    <string name="live_notifications_desc">Pinned notifications display live info from apps, and always appear on the status bar and lock screen</string>
    <!-- Configure Notifications: Title for the notification bubbles option. [CHAR LIMIT=60] -->
    <string name="notification_bubbles_title">Bubbles</string>
    <!-- Title for the toggle shown on the app-level bubbles page  [CHAR LIMIT=60] -->
+17 −0
Original line number Diff line number Diff line
@@ -30,6 +30,23 @@
    <Preference
        android:key="block_desc" />

    <!-- Whether the app can show promoted notifications -->
    <PreferenceCategory
        android:title="@string/live_notifications"
        android:key="promoted_category"
        android:visibility="gone">

        <com.android.settingslib.RestrictedSwitchPreference
            android:key="promoted_switch"
            android:title="@string/live_notifications_switch" />

        <Preference
            android:key="promoted_desc"
            android:summary="@string/live_notifications_desc"
            android:selectable="false"/>

    </PreferenceCategory>

    <!-- Conversations added here -->
    <PreferenceCategory
        android:title="@string/conversations_category_title"
+34 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY

import static com.android.server.notification.Flags.notificationHideUnusedChannels;

import android.app.Flags;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
@@ -66,11 +67,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class NotificationBackend {
    private static final String TAG = "NotificationBackend";
@@ -102,6 +101,9 @@ public class NotificationBackend {
        row.blockedChannelCount = getBlockedChannelCount(row.pkg, row.uid);
        row.channelCount = getChannelCount(row.pkg, row.uid);
        recordAggregatedUsageEvents(context, row);
        if (Flags.uiRichOngoing()) {
            row.canBePromoted = canBePromoted(row.pkg, row.uid);
        }
        return row;
    }

@@ -707,6 +709,35 @@ public class NotificationBackend {
        }
    }

    /**
     * Retrieves whether the app with given package and uid is permitted to post promoted
     * notifications.
     */
    public boolean canBePromoted(String pkg, int uid) {
        try {
            return sINM.appCanBePromoted(pkg, uid);
        } catch (Exception e) {
            Log.w(TAG, "Error calling NoMan", e);
            return false;
        }
    }

    /**
     * Sets whether the app with given package and uid is permitted to post promoted notifications.
     */
    public void setCanBePromoted(String pkg, int uid, boolean allowed) {
        // We shouldn't get here with the flag off, but just in case, do nothing.
        if (!Flags.uiRichOngoing()) {
            Log.wtf(TAG, "tried to setCanBePromoted without flag on");
            return;
        }
        try {
            sINM.setCanBePromoted(pkg, uid, allowed, /* fromUser= */ true);
        } catch (Exception e) {
            Log.w(TAG, "Error calling NoMan", e);
        }
    }

    @VisibleForTesting
    void setNm(INotificationManager inm) {
        sINM = inm;
@@ -748,5 +779,6 @@ public class NotificationBackend {
        public Map<String, NotificationsSentState> sentByChannel;
        public NotificationsSentState sentByApp;
        public boolean showAllChannels = true;
        public boolean canBePromoted;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ public class AppNotificationSettings extends NotificationSettings {
        mControllers.add(new ShowMorePreferenceController(
                context, mDependentFieldListener, mBackend));
        mControllers.add(new BundleListPreferenceController(context, mBackend));
        mControllers.add(new PromotedNotificationsPreferenceController(context, mBackend));
        return new ArrayList<>(mControllers);
    }
}
+83 −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.app;

import android.app.Flags;
import android.content.Context;

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

import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedSwitchPreference;

public class PromotedNotificationsPreferenceController extends
        NotificationPreferenceController implements Preference.OnPreferenceChangeListener {
    private static final String KEY_PROMOTED_CATEGORY = "promoted_category";
    private static final String KEY_PROMOTED_SWITCH = "promoted_switch";

    public PromotedNotificationsPreferenceController(@NonNull Context context,
            @NonNull NotificationBackend backend) {
        super(context, backend);
    }

    @Override
    @NonNull
    public String getPreferenceKey() {
        return KEY_PROMOTED_CATEGORY;
    }

    @Override
    public boolean isAvailable() {
        if (!Flags.uiRichOngoing()) {
            return false;
        }
        return super.isAvailable();
    }

    @Override
    boolean isIncludedInFilter() {
        // not a channel-specific preference; only at the app level
        return false;
    }

    /**
     * Updates the state of the promoted notifications switch. Because this controller governs
     * the full PreferenceCategory, we must find the switch preference within the category first.
     */
    public void updateState(@NonNull Preference preference) {
        PreferenceCategory category = (PreferenceCategory) preference;
        RestrictedSwitchPreference pref = category.findPreference(KEY_PROMOTED_SWITCH);

        if (pref != null && mAppRow != null) {
            pref.setDisabledByAdmin(mAdmin);
            pref.setEnabled(!pref.isDisabledByAdmin());
            pref.setChecked(mAppRow.canBePromoted);
            pref.setOnPreferenceChangeListener(this);
        }
    }

    @Override
    public boolean onPreferenceChange(@NonNull Preference preference, @NonNull Object newValue) {
        final boolean canBePromoted = (Boolean) newValue;
        if (mAppRow != null && mAppRow.canBePromoted != canBePromoted) {
            mAppRow.canBePromoted = canBePromoted;
            mBackend.setCanBePromoted(mAppRow.pkg, mAppRow.uid, canBePromoted);
        }
        return true;
    }
}
Loading