Move channel listing into a pref controller

And a hidden preference category. This makes
hiding/showing the list a lot cleaner and also allows more
of the code to be tested.

Also delete some unused code that no longer complied after
this refactor.

Fixes: 133443871
Test: atest
Change-Id: I4a5fe0e075019bae2df44a0a9dcec26a40ee6d12
(cherry picked from commit a295d71c94)
This commit is contained in:
Julia Reynolds
2019-07-01 13:44:39 -04:00
parent 957463ca00
commit c400ce3c80
12 changed files with 368 additions and 442 deletions

View File

@@ -2594,13 +2594,6 @@
android:value="com.android.settings.notification.AppNotificationSettings" />
</activity>
<!-- Show channel group-level notification settings (group passed in as extras) -->
<activity android:name="Settings$ChannelGroupNotificationSettingsActivity"
android:exported="true">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.notification.ChannelGroupNotificationSettings" />
</activity>
<!-- Show channel-level notification settings (channel passed in as extras) -->
<activity android:name="Settings$ChannelNotificationSettingsActivity"
android:label="@string/notification_channel_title"

20
res/layout/empty_view.xml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>

View File

@@ -30,6 +30,11 @@
android:key="block_desc" />
<!-- Channels/Channel groups added here -->
<PreferenceCategory
android:key="channels"
android:layout="@layout/empty_view"
settings:allowDividerAbove="false"
settings:allowDividerBelow="false" />
<!-- Importance toggle -->
<com.android.settingslib.RestrictedSwitchPreference

View File

@@ -106,7 +106,6 @@ import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
import com.android.settings.notification.AppBubbleNotificationSettings;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.ChannelGroupNotificationSettings;
import com.android.settings.notification.ChannelNotificationSettings;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.NotificationAccessSettings;
@@ -238,7 +237,6 @@ public class SettingsGateway {
AppNotificationSettings.class.getName(),
NotificationAssistantPicker.class.getName(),
ChannelNotificationSettings.class.getName(),
ChannelGroupNotificationSettings.class.getName(),
ApnSettings.class.getName(),
ApnEditor.class.getName(),
WifiCallingSettings.class.getName(),

View File

@@ -20,7 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.android.settings.notification.NotificationSettingsBase.ARG_FROM_SETTINGS;
import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
import android.app.Application;
import android.app.NotificationChannel;
@@ -110,7 +110,7 @@ public class NotificationChannelSlice implements CustomSliceable {
*
* Note:
* When the sent count of notification channels is the same, follow the sorting mechanism from
* {@link com.android.settings.notification.NotificationSettingsBase#mChannelComparator}.
* {@link com.android.settings.notification.ChannelListPreferenceController}.
* Since slice view only shows displayable notification channels, so those deleted ones are
* excluded from the comparison here.
*/
@@ -257,7 +257,6 @@ public class NotificationChannelSlice implements CustomSliceable {
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPackageName);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
final Intent channelIntent = new SubSettingLauncher(mContext)
.setDestination(ChannelNotificationSettings.class.getName())

View File

@@ -16,46 +16,34 @@
package com.android.settings.notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.widget.MasterSwitchPreference;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
/** These settings are per app, so should not be returned in global search results. */
public class AppNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "AppNotificationSettings";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static String KEY_GENERAL_CATEGORY = "categories";
private static String KEY_ADVANCED_CATEGORY = "app_advanced";
private static String KEY_BADGE = "badge";
private static String KEY_APP_LINK = "app_link";
private static String KEY_BUBBLE = "bubble_link_pref";
private static String[] LEGACY_NON_ADVANCED_KEYS = {KEY_BADGE, KEY_APP_LINK, KEY_BUBBLE};
private List<NotificationChannelGroup> mChannelGroupList;
@Override
public int getMetricsCategory() {
return SettingsEnums.NOTIFICATION_APP_NOTIFICATION;
@@ -91,26 +79,6 @@ public class AppNotificationSettings extends NotificationSettingsBase {
return;
}
if (!mShowLegacyChannelConfig) {
// Load channel settings
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mChannelGroupList = mBackend.getGroups(mPkg, mUid).getList();
Collections.sort(mChannelGroupList, mChannelGroupComparator);
return null;
}
@Override
protected void onPostExecute(Void unused) {
if (getHost() == null) {
return;
}
populateList();
}
}.execute();
}
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
controller.displayPreference(getPreferenceScreen());
@@ -154,125 +122,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
mControllers.add(new ChannelListPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
private void populateList() {
if (!mDynamicPreferences.isEmpty()) {
for (Preference p : mDynamicPreferences) {
getPreferenceScreen().removePreference(p);
}
mDynamicPreferences.clear();
}
if (mChannelGroupList.isEmpty()) {
PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
groupCategory.setTitle(R.string.notification_channels);
groupCategory.setKey(KEY_GENERAL_CATEGORY);
getPreferenceScreen().addPreference(groupCategory);
mDynamicPreferences.add(groupCategory);
Preference empty = new Preference(getPrefContext());
empty.setTitle(R.string.no_channels);
empty.setEnabled(false);
groupCategory.addPreference(empty);
} else {
populateGroupList();
mImportanceListener.onImportanceChanged();
}
}
private void populateGroupList() {
for (NotificationChannelGroup group : mChannelGroupList) {
PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
groupCategory.setOrderingAsAdded(true);
getPreferenceScreen().addPreference(groupCategory);
mDynamicPreferences.add(groupCategory);
if (group.getId() == null) {
if (mChannelGroupList.size() > 1) {
groupCategory.setTitle(R.string.notification_channels_other);
}
groupCategory.setKey(KEY_GENERAL_CATEGORY);
} else {
groupCategory.setTitle(group.getName());
groupCategory.setKey(group.getId());
populateGroupToggle(groupCategory, group);
}
if (!group.isBlocked()) {
final List<NotificationChannel> channels = group.getChannels();
Collections.sort(channels, mChannelComparator);
int N = channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel channel = channels.get(i);
populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
}
}
}
}
protected void populateGroupToggle(final PreferenceGroup parent,
NotificationChannelGroup group) {
RestrictedSwitchPreference preference = new RestrictedSwitchPreference(getPrefContext());
preference.setTitle(R.string.notification_switch_label);
preference.setEnabled(mSuspendedAppsAdmin == null
&& isChannelGroupBlockable(group));
preference.setChecked(!group.isBlocked());
preference.setOnPreferenceClickListener(preference1 -> {
final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
group.setBlocked(!allowGroup);
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
onGroupBlockStateChanged(group);
return true;
});
parent.addPreference(preference);
}
private Comparator<NotificationChannelGroup> mChannelGroupComparator =
new Comparator<NotificationChannelGroup>() {
@Override
public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
// Non-grouped channels (in placeholder group with a null id) come last
if (left.getId() == null && right.getId() != null) {
return 1;
} else if (right.getId() == null && left.getId() != null) {
return -1;
}
return left.getId().compareTo(right.getId());
}
};
protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
if (group == null) {
return;
}
PreferenceGroup groupGroup = (
PreferenceGroup) getPreferenceScreen().findPreference(group.getId());
if (groupGroup != null) {
if (group.isBlocked()) {
List<Preference> toRemove = new ArrayList<>();
int childCount = groupGroup.getPreferenceCount();
for (int i = 0; i < childCount; i++) {
Preference pref = groupGroup.getPreference(i);
if (pref instanceof MasterSwitchPreference) {
toRemove.add(pref);
}
}
for (Preference pref : toRemove) {
groupGroup.removePreference(pref);
}
} else {
final List<NotificationChannel> channels = group.getChannels();
Collections.sort(channels, mChannelComparator);
int N = channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel channel = channels.get(i);
populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
}
}
}
}
}

View File

@@ -1,106 +0,0 @@
/*
* Copyright (C) 2017 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.app.NotificationChannel;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.util.Log;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ChannelGroupNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "ChannelGroupSettings";
@Override
public int getMetricsCategory() {
return SettingsEnums.NOTIFICATION_CHANNEL_GROUP;
}
@Override
public void onResume() {
super.onResume();
if (mAppRow == null || mChannelGroup == null) {
Log.w(TAG, "Missing package or uid or packageinfo or group");
finish();
return;
}
populateChannelList();
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
controller.displayPreference(getPreferenceScreen());
}
updatePreferenceStates();
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.notification_group_settings;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
mControllers.add(new HeaderPreferenceController(context, this));
mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
mControllers.add(new AppLinkPreferenceController(context));
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new DescriptionPreferenceController(context));
return new ArrayList<>(mControllers);
}
private void populateChannelList() {
if (!mDynamicPreferences.isEmpty()) {
// If there's anything in mDynamicPreferences, we've called populateChannelList twice.
// Clear out existing channels and log.
Log.w(TAG, "Notification channel group posted twice to settings - old size " +
mDynamicPreferences.size() + ", new size " + mDynamicPreferences.size());
for (Preference p : mDynamicPreferences) {
getPreferenceScreen().removePreference(p);
}
}
if (mChannelGroup.getChannels().isEmpty()) {
Preference empty = new Preference(getPrefContext());
empty.setTitle(R.string.no_channels);
empty.setEnabled(false);
getPreferenceScreen().addPreference(empty);
mDynamicPreferences.add(empty);
} else {
final List<NotificationChannel> channels = mChannelGroup.getChannels();
Collections.sort(channels, mChannelComparator);
for (NotificationChannel channel : channels) {
mDynamicPreferences.add(populateSingleChannelPrefs(
getPreferenceScreen(), channel, mChannelGroup.isBlocked()));
}
}
}
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (C) 2019 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 static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.graphics.BlendMode;
import android.graphics.BlendModeColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.widget.MasterSwitchPreference;
import com.android.settingslib.RestrictedSwitchPreference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.SwitchPreference;
public class ChannelListPreferenceController extends NotificationPreferenceController {
private static final String KEY = "channels";
private static String KEY_GENERAL_CATEGORY = "categories";
public static final String ARG_FROM_SETTINGS = "fromSettings";
private List<NotificationChannelGroup> mChannelGroupList;
private PreferenceCategory mPreference;
public ChannelListPreferenceController(Context context, NotificationBackend backend) {
super(context, backend);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
if (mAppRow == null) {
return false;
}
if (mAppRow.banned) {
return false;
}
if (mChannel != null) {
if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
return false;
}
}
return true;
}
@Override
public void updateState(Preference preference) {
mPreference = (PreferenceCategory) preference;
// Load channel settings
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList();
Collections.sort(mChannelGroupList, mChannelGroupComparator);
return null;
}
@Override
protected void onPostExecute(Void unused) {
if (mContext == null) {
return;
}
populateList();
}
}.execute();
}
private void populateList() {
// TODO: if preference has children, compare with newly loaded list
mPreference.removeAll();
if (mChannelGroupList.isEmpty()) {
PreferenceCategory groupCategory = new PreferenceCategory(mContext);
groupCategory.setTitle(R.string.notification_channels);
groupCategory.setKey(KEY_GENERAL_CATEGORY);
mPreference.addPreference(groupCategory);
Preference empty = new Preference(mContext);
empty.setTitle(R.string.no_channels);
empty.setEnabled(false);
groupCategory.addPreference(empty);
} else {
populateGroupList();
}
}
private void populateGroupList() {
for (NotificationChannelGroup group : mChannelGroupList) {
PreferenceCategory groupCategory = new PreferenceCategory(mContext);
groupCategory.setOrderingAsAdded(true);
mPreference.addPreference(groupCategory);
if (group.getId() == null) {
if (mChannelGroupList.size() > 1) {
groupCategory.setTitle(R.string.notification_channels_other);
}
groupCategory.setKey(KEY_GENERAL_CATEGORY);
} else {
groupCategory.setTitle(group.getName());
groupCategory.setKey(group.getId());
populateGroupToggle(groupCategory, group);
}
if (!group.isBlocked()) {
final List<NotificationChannel> channels = group.getChannels();
Collections.sort(channels, mChannelComparator);
int N = channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel channel = channels.get(i);
populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
}
}
}
}
protected void populateGroupToggle(final PreferenceGroup parent,
NotificationChannelGroup group) {
RestrictedSwitchPreference preference =
new RestrictedSwitchPreference(mContext);
preference.setTitle(R.string.notification_switch_label);
preference.setEnabled(mAdmin == null
&& isChannelGroupBlockable(group));
preference.setChecked(!group.isBlocked());
preference.setOnPreferenceClickListener(preference1 -> {
final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
group.setBlocked(!allowGroup);
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
onGroupBlockStateChanged(group);
return true;
});
parent.addPreference(preference);
}
protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
final NotificationChannel channel, final boolean groupBlocked) {
MasterSwitchPreference channelPref = new MasterSwitchPreference(mContext);
channelPref.setSwitchEnabled(mAdmin == null
&& isChannelBlockable(channel)
&& isChannelConfigurable(channel)
&& !groupBlocked);
channelPref.setIcon(null);
if (channel.getImportance() > IMPORTANCE_LOW) {
channelPref.setIcon(getAlertingIcon());
}
channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
channelPref.setKey(channel.getId());
channelPref.setTitle(channel.getName());
channelPref.setSummary(NotificationBackend.getSentSummary(
mContext, mAppRow.sentByChannel.get(channel.getId()), false));
channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
Bundle channelArgs = new Bundle();
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
channelPref.setIntent(new SubSettingLauncher(mContext)
.setDestination(ChannelNotificationSettings.class.getName())
.setArguments(channelArgs)
.setTitleRes(R.string.notification_channel_title)
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
.toIntent());
channelPref.setOnPreferenceChangeListener(
(preference, o) -> {
boolean value = (Boolean) o;
int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
channel.setImportance(importance);
channel.lockFields(
NotificationChannel.USER_LOCKED_IMPORTANCE);
MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
channelPref1.setIcon(null);
if (channel.getImportance() > IMPORTANCE_LOW) {
channelPref1.setIcon(getAlertingIcon());
}
toggleBehaviorIconState(channelPref1.getIcon(),
importance != IMPORTANCE_NONE);
mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, channel);
return true;
});
if (parent.findPreference(channelPref.getKey()) == null) {
parent.addPreference(channelPref);
}
return channelPref;
}
private Drawable getAlertingIcon() {
Drawable icon = mContext.getDrawable(R.drawable.ic_notifications_alert);
icon.setTintList(Utils.getColorAccent(mContext));
return icon;
}
private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
if (icon == null) return;
LayerDrawable layerDrawable = (LayerDrawable) icon;
GradientDrawable background =
(GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
if (background == null) return;
if (enabled) {
background.clearColorFilter();
} else {
background.setColorFilter(new BlendModeColorFilter(
mContext.getColor(R.color.material_grey_300),
BlendMode.SRC_IN));
}
}
protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
if (group == null) {
return;
}
PreferenceGroup groupGroup = mPreference.findPreference(group.getId());
if (groupGroup != null) {
if (group.isBlocked()) {
List<Preference> toRemove = new ArrayList<>();
int childCount = groupGroup.getPreferenceCount();
for (int i = 0; i < childCount; i++) {
Preference pref = groupGroup.getPreference(i);
if (pref instanceof MasterSwitchPreference) {
toRemove.add(pref);
}
}
for (Preference pref : toRemove) {
groupGroup.removePreference(pref);
}
} else {
final List<NotificationChannel> channels = group.getChannels();
Collections.sort(channels, mChannelComparator);
int N = channels.size();
for (int i = 0; i < N; i++) {
final NotificationChannel channel = channels.get(i);
populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
}
}
}
}
private Comparator<NotificationChannelGroup> mChannelGroupComparator =
new Comparator<NotificationChannelGroup>() {
@Override
public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
// Non-grouped channels (in placeholder group with a null id) come last
if (left.getId() == null && right.getId() != null) {
return 1;
} else if (right.getId() == null && left.getId() != null) {
return -1;
}
return left.getId().compareTo(right.getId());
}
};
protected Comparator<NotificationChannel> mChannelComparator =
(left, right) -> {
if (left.isDeleted() != right.isDeleted()) {
return Boolean.compare(left.isDeleted(), right.isDeleted());
} else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Uncategorized/miscellaneous legacy channel goes last
return 1;
} else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
return -1;
}
return left.getId().compareTo(right.getId());
};
}

View File

@@ -16,6 +16,8 @@
package com.android.settings.notification;
import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;

View File

@@ -113,25 +113,40 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
}
protected boolean isChannelBlockable() {
if (mChannel != null && mAppRow != null) {
if (mChannel.isImportanceLockedByCriticalDeviceFunction()
|| mChannel.isImportanceLockedByOEM()) {
return mChannel.getImportance() == IMPORTANCE_NONE;
return isChannelBlockable(mChannel);
}
protected boolean isChannelBlockable(NotificationChannel channel) {
if (channel != null && mAppRow != null) {
if (channel.isImportanceLockedByCriticalDeviceFunction()
|| channel.isImportanceLockedByOEM()) {
return channel.getImportance() == IMPORTANCE_NONE;
}
return mChannel.isBlockableSystem() || !mAppRow.systemApp
|| mChannel.getImportance() == IMPORTANCE_NONE;
return channel.isBlockableSystem() || !mAppRow.systemApp
|| channel.getImportance() == IMPORTANCE_NONE;
}
return false;
}
protected boolean isChannelConfigurable(NotificationChannel channel) {
if (channel != null && mAppRow != null) {
return !channel.isImportanceLockedByOEM();
}
return false;
}
protected boolean isChannelGroupBlockable() {
if (mChannelGroup != null && mAppRow != null) {
return isChannelGroupBlockable(mChannelGroup);
}
protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
if (group != null && mAppRow != null) {
if (!mAppRow.systemApp) {
return true;
}
return mChannelGroup.isBlocked();
return group.isBlocked();
}
return false;
}

View File

@@ -67,7 +67,6 @@ import java.util.List;
abstract public class NotificationSettingsBase extends DashboardFragment {
private static final String TAG = "NotifiSettingsBase";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final String ARG_FROM_SETTINGS = "fromSettings";
protected PackageManager mPm;
protected NotificationBackend mBackend = new NotificationBackend();
@@ -88,7 +87,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
protected boolean mListeningToPackageRemove;
protected List<NotificationPreferenceController> mControllers = new ArrayList<>();
protected List<Preference> mDynamicPreferences = new ArrayList<>();
protected ImportanceListener mImportanceListener = new ImportanceListener();
protected Intent mIntent;
@@ -126,7 +124,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
mContext, mPkg, mUserId);
loadChannel();
loadAppRow();
loadChannelGroup();
@@ -280,135 +277,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
return null;
}
private Drawable getAlertingIcon() {
Drawable icon = getContext().getDrawable(R.drawable.ic_notifications_alert);
icon.setTintList(Utils.getColorAccent(getContext()));
return icon;
}
protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
final NotificationChannel channel, final boolean groupBlocked) {
MasterSwitchPreference channelPref = new MasterSwitchPreference(getPrefContext());
channelPref.setSwitchEnabled(mSuspendedAppsAdmin == null
&& isChannelBlockable(channel)
&& isChannelConfigurable(channel)
&& !groupBlocked);
channelPref.setIcon(null);
if (channel.getImportance() > IMPORTANCE_LOW) {
channelPref.setIcon(getAlertingIcon());
}
channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
channelPref.setKey(channel.getId());
channelPref.setTitle(channel.getName());
channelPref.setSummary(NotificationBackend.getSentSummary(
mContext, mAppRow.sentByChannel.get(channel.getId()), false));
channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
Bundle channelArgs = new Bundle();
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
channelPref.setIntent(new SubSettingLauncher(getActivity())
.setDestination(ChannelNotificationSettings.class.getName())
.setArguments(channelArgs)
.setTitleRes(R.string.notification_channel_title)
.setSourceMetricsCategory(getMetricsCategory())
.toIntent());
channelPref.setOnPreferenceChangeListener(
(preference, o) -> {
boolean value = (Boolean) o;
int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
channel.setImportance(importance);
channel.lockFields(
NotificationChannel.USER_LOCKED_IMPORTANCE);
MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
channelPref1.setIcon(null);
if (channel.getImportance() > IMPORTANCE_LOW) {
channelPref1.setIcon(getAlertingIcon());
}
toggleBehaviorIconState(channelPref1.getIcon(),
importance != IMPORTANCE_NONE);
mBackend.updateChannel(mPkg, mUid, channel);
return true;
});
if (parent.findPreference(channelPref.getKey()) == null) {
parent.addPreference(channelPref);
}
return channelPref;
}
private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
if (icon == null) return;
LayerDrawable layerDrawable = (LayerDrawable) icon;
GradientDrawable background =
(GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
if (background == null) return;
if (enabled) {
background.clearColorFilter();
} else {
background.setColorFilter(new BlendModeColorFilter(
mContext.getColor(R.color.material_grey_300),
BlendMode.SRC_IN));
}
}
protected boolean isChannelConfigurable(NotificationChannel channel) {
if (channel != null && mAppRow != null) {
return !channel.isImportanceLockedByOEM();
}
return false;
}
protected boolean isChannelBlockable(NotificationChannel channel) {
if (channel != null && mAppRow != null) {
if (!mAppRow.systemApp) {
return true;
}
if (channel.isImportanceLockedByCriticalDeviceFunction()) {
return false;
}
if (channel.isImportanceLockedByOEM()) {
return false;
}
return channel.isBlockableSystem()
|| channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
}
return false;
}
protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
if (group != null && mAppRow != null) {
if (!mAppRow.systemApp) {
return true;
}
return group.isBlocked();
}
return false;
}
protected void setVisible(Preference p, boolean visible) {
setVisible(getPreferenceScreen(), p, visible);
}
protected void setVisible(PreferenceGroup parent, Preference p, boolean visible) {
final boolean isVisible = parent.findPreference(p.getKey()) != null;
if (isVisible == visible) return;
if (visible) {
parent.addPreference(p);
} else {
parent.removePreference(p);
}
}
protected void startListeningToPackageRemove() {
if (mListeningToPackageRemove) {
return;
@@ -445,20 +313,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
}
};
protected Comparator<NotificationChannel> mChannelComparator =
(left, right) -> {
if (left.isDeleted() != right.isDeleted()) {
return Boolean.compare(left.isDeleted(), right.isDeleted());
} else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Uncategorized/miscellaneous legacy channel goes last
return 1;
} else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
return -1;
}
return left.getId().compareTo(right.getId());
};
protected class ImportanceListener {
protected void onImportanceChanged() {
final PreferenceScreen screen = getPreferenceScreen();
@@ -466,20 +320,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
controller.displayPreference(screen);
}
updatePreferenceStates();
boolean hideDynamicFields = false;
if (mAppRow == null || mAppRow.banned) {
hideDynamicFields = true;
} else {
if (mChannel != null) {
hideDynamicFields = mChannel.getImportance() == IMPORTANCE_NONE;
} else if (mChannelGroup != null) {
hideDynamicFields = mChannelGroup.isBlocked();
}
}
for (Preference preference : mDynamicPreferences) {
setVisible(getPreferenceScreen(), preference, !hideDynamicFields);
}
}
}
}

View File

@@ -51,7 +51,6 @@ com.android.settings.network.ApnEditor
com.android.settings.network.ApnSettings
com.android.settings.network.telephony.NetworkSelectSettings
com.android.settings.notification.AppNotificationSettings
com.android.settings.notification.ChannelGroupNotificationSettings
com.android.settings.notification.ChannelNotificationSettings
com.android.settings.notification.NotificationStation
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment