1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.notification.app; 18 19 import static android.app.NotificationChannel.NEWS_ID; 20 import static android.app.NotificationChannel.PROMOTIONS_ID; 21 import static android.app.NotificationChannel.RECS_ID; 22 import static android.app.NotificationChannel.SOCIAL_MEDIA_ID; 23 import static android.app.NotificationManager.IMPORTANCE_LOW; 24 import static android.app.NotificationManager.IMPORTANCE_NONE; 25 26 import static com.android.server.notification.Flags.notificationHideUnusedChannels; 27 28 import android.app.NotificationChannel; 29 import android.app.NotificationChannelGroup; 30 import android.app.settings.SettingsEnums; 31 import android.content.Context; 32 import android.graphics.drawable.Drawable; 33 import android.os.AsyncTask; 34 import android.os.Bundle; 35 import android.provider.Settings; 36 import android.service.notification.Flags; 37 import android.text.TextUtils; 38 39 import androidx.annotation.NonNull; 40 import androidx.annotation.Nullable; 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceCategory; 43 import androidx.preference.PreferenceGroup; 44 import androidx.preference.TwoStatePreference; 45 46 import com.android.settings.R; 47 import com.android.settings.Utils; 48 import com.android.settings.applications.AppInfoBase; 49 import com.android.settings.core.SubSettingLauncher; 50 import com.android.settings.notification.NotificationBackend; 51 import com.android.settingslib.PrimarySwitchPreference; 52 import com.android.settingslib.RestrictedSwitchPreference; 53 54 import java.util.ArrayList; 55 import java.util.Collections; 56 import java.util.List; 57 58 public class BundleListPreferenceController extends NotificationPreferenceController { 59 60 private static final String KEY = "bundles"; 61 BundleListPreferenceController(Context context, NotificationBackend backend)62 public BundleListPreferenceController(Context context, NotificationBackend backend) { 63 super(context, backend); 64 } 65 66 @Override getPreferenceKey()67 public String getPreferenceKey() { 68 return KEY; 69 } 70 71 @Override isAvailable()72 public boolean isAvailable() { 73 if (!Flags.notificationClassification()) { 74 return false; 75 } 76 if (mAppRow == null) { 77 return false; 78 } 79 if (mAppRow.banned || mAppRow.lockedImportance || mAppRow.systemApp) { 80 return false; 81 } 82 return true; 83 } 84 85 @Override isIncludedInFilter()86 boolean isIncludedInFilter() { 87 return false; 88 } 89 90 @Override updateState(Preference preference)91 public void updateState(Preference preference) { 92 PreferenceCategory category = (PreferenceCategory) preference; 93 94 NotificationChannel promos = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID); 95 if (promos != null) { 96 createOrUpdatePrefForChannel(category, promos); 97 } 98 NotificationChannel recs = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID); 99 if (recs != null) { 100 createOrUpdatePrefForChannel(category, recs); 101 } 102 NotificationChannel social = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID); 103 if (social != null) { 104 createOrUpdatePrefForChannel(category, social); 105 } 106 NotificationChannel news = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID); 107 if (news != null) { 108 createOrUpdatePrefForChannel(category, news); 109 } 110 111 int preferenceCount = ((PreferenceGroup) preference).getPreferenceCount(); 112 if (preferenceCount == 0) { 113 preference.setVisible(false); 114 } 115 } 116 117 @NonNull createOrUpdatePrefForChannel( @onNull PreferenceGroup groupPrefGroup, NotificationChannel channel)118 private void createOrUpdatePrefForChannel( 119 @NonNull PreferenceGroup groupPrefGroup, NotificationChannel channel) { 120 int preferenceCount = groupPrefGroup.getPreferenceCount(); 121 for (int i = 0; i < preferenceCount; i++) { 122 Preference preference = groupPrefGroup.getPreference(i); 123 if (channel.getId().equals(preference.getKey())) { 124 updateSingleChannelPrefs((PrimarySwitchPreference) preference, channel); 125 return; 126 } 127 } 128 PrimarySwitchPreference channelPref = new PrimarySwitchPreference(mContext); 129 channelPref.setKey(channel.getId()); 130 updateSingleChannelPrefs(channelPref, channel); 131 groupPrefGroup.addPreference(channelPref); 132 } 133 134 /** Update the properties of the channel preference with the values from the channel object. */ updateSingleChannelPrefs(@onNull final PrimarySwitchPreference channelPref, @NonNull final NotificationChannel channel)135 private void updateSingleChannelPrefs(@NonNull final PrimarySwitchPreference channelPref, 136 @NonNull final NotificationChannel channel) { 137 channelPref.setSwitchEnabled(mAdmin == null); 138 if (channel.getImportance() > IMPORTANCE_LOW) { 139 channelPref.setIcon(getAlertingIcon()); 140 } else { 141 channelPref.setIcon(mContext.getDrawable(R.drawable.empty_icon)); 142 } 143 channelPref.setIconSize(PrimarySwitchPreference.ICON_SIZE_SMALL); 144 channelPref.setTitle(channel.getName()); 145 channelPref.setSummary(NotificationBackend.getSentSummary( 146 mContext, mAppRow.sentByChannel.get(channel.getId()), false)); 147 channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE); 148 Bundle channelArgs = new Bundle(); 149 channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid); 150 channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg); 151 channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId()); 152 channelPref.setIntent(new SubSettingLauncher(mContext) 153 .setDestination(ChannelNotificationSettings.class.getName()) 154 .setArguments(channelArgs) 155 .setTitleRes(R.string.notification_channel_title) 156 .setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION) 157 .toIntent()); 158 159 channelPref.setOnPreferenceChangeListener( 160 (preference, o) -> { 161 boolean value = (Boolean) o; 162 int importance = value 163 ? Math.max(channel.getOriginalImportance(), IMPORTANCE_LOW) 164 : IMPORTANCE_NONE; 165 channel.setImportance(importance); 166 channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); 167 PrimarySwitchPreference channelPref1 = (PrimarySwitchPreference) preference; 168 channelPref1.setIcon(R.drawable.empty_icon); 169 if (channel.getImportance() > IMPORTANCE_LOW) { 170 channelPref1.setIcon(getAlertingIcon()); 171 } 172 mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, channel); 173 174 return true; 175 }); 176 } 177 getAlertingIcon()178 private Drawable getAlertingIcon() { 179 Drawable icon = mContext.getDrawable(R.drawable.ic_notifications_alert); 180 icon.setTintList(Utils.getColorAccent(mContext)); 181 return icon; 182 } 183 } 184