Fix binder error when an app has many channels
By making the channel list inside of NotificationChannelGroup a ParceledListSlice also Test: NotificationChannelGroupTest Test: NotificationManagerServiceTest Test: PreferencesHelperTest Bug: 215072888 Change-Id: I391ce0b104af99a11b3a5db31fb8d0321f3a4988
This commit is contained in:
@@ -20,6 +20,7 @@ import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
@@ -66,7 +67,7 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
private CharSequence mName;
|
||||
private String mDescription;
|
||||
private boolean mBlocked;
|
||||
private List<NotificationChannel> mChannels = new ArrayList<>();
|
||||
private ParceledListSlice<NotificationChannel> mChannels;
|
||||
// Bitwise representation of fields that have been changed by the user
|
||||
private int mUserLockedFields;
|
||||
|
||||
@@ -100,7 +101,8 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
} else {
|
||||
mDescription = null;
|
||||
}
|
||||
in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class);
|
||||
mChannels = in.readParcelable(
|
||||
NotificationChannelGroup.class.getClassLoader(), ParceledListSlice.class);
|
||||
mBlocked = in.readBoolean();
|
||||
mUserLockedFields = in.readInt();
|
||||
}
|
||||
@@ -127,7 +129,7 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
} else {
|
||||
dest.writeByte((byte) 0);
|
||||
}
|
||||
dest.writeParcelableList(mChannels, flags);
|
||||
dest.writeParcelable(mChannels, flags);
|
||||
dest.writeBoolean(mBlocked);
|
||||
dest.writeInt(mUserLockedFields);
|
||||
}
|
||||
@@ -157,7 +159,7 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
* Returns the list of channels that belong to this group
|
||||
*/
|
||||
public List<NotificationChannel> getChannels() {
|
||||
return mChannels;
|
||||
return mChannels == null ? new ArrayList<>() : mChannels.getList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,18 +190,11 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
mBlocked = blocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void addChannel(NotificationChannel channel) {
|
||||
mChannels.add(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void setChannels(List<NotificationChannel> channels) {
|
||||
mChannels = channels;
|
||||
mChannels = new ParceledListSlice<>(channels);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +329,7 @@ public final class NotificationChannelGroup implements Parcelable {
|
||||
proto.write(NotificationChannelGroupProto.NAME, mName.toString());
|
||||
proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription);
|
||||
proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked);
|
||||
for (NotificationChannel channel : mChannels) {
|
||||
for (NotificationChannel channel : mChannels.getList()) {
|
||||
channel.dumpDebug(proto, NotificationChannelGroupProto.CHANNELS);
|
||||
}
|
||||
proto.end(token);
|
||||
|
||||
@@ -98,7 +98,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun testPrepareDialogForApp_onlyDefaultChannel() {
|
||||
group.addChannel(channelDefault)
|
||||
group.channels = listOf(channelDefault)
|
||||
|
||||
controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID,
|
||||
setOf(channelDefault), appIcon, clickListener)
|
||||
|
||||
@@ -86,6 +86,7 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -1327,16 +1328,17 @@ public class PreferencesHelper implements RankingConfig {
|
||||
return null;
|
||||
}
|
||||
NotificationChannelGroup group = r.groups.get(groupId).clone();
|
||||
group.setChannels(new ArrayList<>());
|
||||
ArrayList channels = new ArrayList();
|
||||
int N = r.channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel nc = r.channels.valueAt(i);
|
||||
if (includeDeleted || !nc.isDeleted()) {
|
||||
if (groupId.equals(nc.getGroup())) {
|
||||
group.addChannel(nc);
|
||||
channels.add(nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
group.setChannels(channels);
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -1357,44 +1359,48 @@ public class PreferencesHelper implements RankingConfig {
|
||||
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
|
||||
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
|
||||
Objects.requireNonNull(pkg);
|
||||
Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
|
||||
List<NotificationChannelGroup> groups = new ArrayList<>();
|
||||
synchronized (mPackagePreferences) {
|
||||
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
|
||||
if (r == null) {
|
||||
return ParceledListSlice.emptyList();
|
||||
}
|
||||
NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
|
||||
Map<String, ArrayList<NotificationChannel>> groupedChannels = new HashMap();
|
||||
int N = r.channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel nc = r.channels.valueAt(i);
|
||||
if (includeDeleted || !nc.isDeleted()) {
|
||||
if (nc.getGroup() != null) {
|
||||
if (r.groups.get(nc.getGroup()) != null) {
|
||||
NotificationChannelGroup ncg = groups.get(nc.getGroup());
|
||||
if (ncg == null) {
|
||||
ncg = r.groups.get(nc.getGroup()).clone();
|
||||
ncg.setChannels(new ArrayList<>());
|
||||
groups.put(nc.getGroup(), ncg);
|
||||
|
||||
}
|
||||
ncg.addChannel(nc);
|
||||
ArrayList<NotificationChannel> channels = groupedChannels.getOrDefault(
|
||||
nc.getGroup(), new ArrayList<>());
|
||||
channels.add(nc);
|
||||
groupedChannels.put(nc.getGroup(), channels);
|
||||
}
|
||||
} else {
|
||||
nonGrouped.addChannel(nc);
|
||||
ArrayList<NotificationChannel> channels = groupedChannels.getOrDefault(
|
||||
null, new ArrayList<>());
|
||||
channels.add(nc);
|
||||
groupedChannels.put(null, channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (includeNonGrouped && nonGrouped.getChannels().size() > 0) {
|
||||
groups.put(null, nonGrouped);
|
||||
}
|
||||
if (includeEmpty) {
|
||||
for (NotificationChannelGroup group : r.groups.values()) {
|
||||
if (!groups.containsKey(group.getId())) {
|
||||
groups.put(group.getId(), group);
|
||||
}
|
||||
for (NotificationChannelGroup group : r.groups.values()) {
|
||||
ArrayList<NotificationChannel> channels =
|
||||
groupedChannels.getOrDefault(group.getId(), new ArrayList<>());
|
||||
if (includeEmpty || !channels.isEmpty()) {
|
||||
NotificationChannelGroup clone = group.clone();
|
||||
clone.setChannels(channels);
|
||||
groups.add(clone);
|
||||
}
|
||||
}
|
||||
return new ParceledListSlice<>(new ArrayList<>(groups.values()));
|
||||
|
||||
if (includeNonGrouped && groupedChannels.containsKey(null)) {
|
||||
NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
|
||||
nonGrouped.setChannels(groupedChannels.get(null));
|
||||
groups.add(nonGrouped);
|
||||
}
|
||||
return new ParceledListSlice<>(groups);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user