Better deletions
- Allow apps to delete notification groups (which cascade to delete all channels therein) - Allow apps to get their groups, so they know what they might want to delete - Don't throw if someone tries to delete something that already doesn't exist. Change-Id: I5f6e25497c5da1e57b52737586e86097332f88f9 Fixes: 36245468 Fixes: 36127382 Test: runtest systemui-notification, cts
This commit is contained in:
@@ -5548,12 +5548,14 @@ package android.app {
|
||||
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
|
||||
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
|
||||
method public void deleteNotificationChannel(java.lang.String);
|
||||
method public void deleteNotificationChannelGroup(java.lang.String);
|
||||
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
|
||||
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
|
||||
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
|
||||
method public final int getCurrentInterruptionFilter();
|
||||
method public int getImportance();
|
||||
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
|
||||
method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
|
||||
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
|
||||
method public android.app.NotificationManager.Policy getNotificationPolicy();
|
||||
method public boolean isNotificationPolicyAccessGranted();
|
||||
|
||||
@@ -5751,12 +5751,14 @@ package android.app {
|
||||
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
|
||||
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
|
||||
method public void deleteNotificationChannel(java.lang.String);
|
||||
method public void deleteNotificationChannelGroup(java.lang.String);
|
||||
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
|
||||
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
|
||||
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
|
||||
method public final int getCurrentInterruptionFilter();
|
||||
method public int getImportance();
|
||||
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
|
||||
method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
|
||||
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
|
||||
method public android.app.NotificationManager.Policy getNotificationPolicy();
|
||||
method public boolean isNotificationPolicyAccessGranted();
|
||||
|
||||
@@ -5558,6 +5558,7 @@ package android.app {
|
||||
method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
|
||||
method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
|
||||
method public void deleteNotificationChannel(java.lang.String);
|
||||
method public void deleteNotificationChannelGroup(java.lang.String);
|
||||
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
|
||||
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
|
||||
method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
|
||||
@@ -5565,6 +5566,7 @@ package android.app {
|
||||
method public android.content.ComponentName getEffectsSuppressor();
|
||||
method public int getImportance();
|
||||
method public android.app.NotificationChannel getNotificationChannel(java.lang.String);
|
||||
method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups();
|
||||
method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
|
||||
method public android.app.NotificationManager.Policy getNotificationPolicy();
|
||||
method public boolean isNotificationPolicyAccessGranted();
|
||||
|
||||
@@ -67,6 +67,8 @@ interface INotificationManager
|
||||
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
|
||||
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
|
||||
int getDeletedChannelCount(String pkg, int uid);
|
||||
void deleteNotificationChannelGroup(String pkg, String channelGroupId);
|
||||
ParceledListSlice getNotificationChannelGroups(String pkg);
|
||||
|
||||
// TODO: Remove this when callers have been migrated to the equivalent
|
||||
// INotificationListener method.
|
||||
|
||||
@@ -497,6 +497,30 @@ public class NotificationManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all notification channel groups belonging to the calling app.
|
||||
*/
|
||||
public List<NotificationChannelGroup> getNotificationChannelGroups() {
|
||||
INotificationManager service = getService();
|
||||
try {
|
||||
return service.getNotificationChannelGroups(mContext.getPackageName()).getList();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given notification channel group.
|
||||
*/
|
||||
public void deleteNotificationChannelGroup(String groupId) {
|
||||
INotificationManager service = getService();
|
||||
try {
|
||||
service.deleteNotificationChannelGroup(mContext.getPackageName(), groupId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -159,6 +159,8 @@ import com.android.server.notification.ManagedServices.UserProfiles;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@@ -1658,8 +1660,7 @@ public class NotificationManagerService extends SystemService {
|
||||
public NotificationChannel getNotificationChannelForPackage(String pkg, int uid,
|
||||
String channelId, boolean includeDeleted) {
|
||||
checkCallerIsSystem();
|
||||
return mRankingHelper.getNotificationChannel
|
||||
(pkg, uid, channelId, includeDeleted);
|
||||
return mRankingHelper.getNotificationChannel(pkg, uid, channelId, includeDeleted);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1674,6 +1675,27 @@ public class NotificationManagerService extends SystemService {
|
||||
savePolicyFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(
|
||||
String pkg) {
|
||||
checkCallerIsSystemOrSameApp(pkg);
|
||||
return new ParceledListSlice<>(new ArrayList(
|
||||
mRankingHelper.getNotificationChannelGroups(pkg, Binder.getCallingUid())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteNotificationChannelGroup(String pkg, String channelGroupId) {
|
||||
checkCallerIsSystemOrSameApp(pkg);
|
||||
|
||||
List<String> deletedChannelIds = mRankingHelper.deleteNotificationChannelGroup(
|
||||
pkg, Binder.getCallingUid(), channelGroupId);
|
||||
for (int i = 0; i < deletedChannelIds.size(); i++) {
|
||||
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannelIds.get(i), 0, 0, true,
|
||||
UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
|
||||
}
|
||||
savePolicyFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNotificationChannelForPackage(String pkg, int uid,
|
||||
NotificationChannel channel) {
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.server.notification;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
@@ -654,8 +652,6 @@ public class RankingHelper implements RankingConfig {
|
||||
|
||||
@Override
|
||||
public void deleteNotificationChannel(String pkg, int uid, String channelId) {
|
||||
Preconditions.checkNotNull(pkg);
|
||||
Preconditions.checkNotNull(channelId);
|
||||
Record r = getRecord(pkg, uid);
|
||||
if (r == null) {
|
||||
return;
|
||||
@@ -667,6 +663,7 @@ public class RankingHelper implements RankingConfig {
|
||||
LogMaker lm = getChannelLog(channel, pkg);
|
||||
lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
|
||||
MetricsLogger.action(lm);
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -679,6 +676,7 @@ public class RankingHelper implements RankingConfig {
|
||||
return;
|
||||
}
|
||||
r.channels.remove(channelId);
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -695,6 +693,7 @@ public class RankingHelper implements RankingConfig {
|
||||
r.channels.remove(key);
|
||||
}
|
||||
}
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
|
||||
@@ -719,12 +718,15 @@ public class RankingHelper implements RankingConfig {
|
||||
final NotificationChannel nc = r.channels.valueAt(i);
|
||||
if (includeDeleted || !nc.isDeleted()) {
|
||||
if (nc.getGroup() != null) {
|
||||
NotificationChannelGroup ncg = groups.get(nc.getGroup());
|
||||
if (ncg == null ) {
|
||||
ncg = r.groups.get(nc.getGroup()).clone();
|
||||
groups.put(nc.getGroup(), ncg);
|
||||
if (r.groups.get(nc.getGroup()) != null) {
|
||||
NotificationChannelGroup ncg = groups.get(nc.getGroup());
|
||||
if (ncg == null) {
|
||||
ncg = r.groups.get(nc.getGroup()).clone();
|
||||
groups.put(nc.getGroup(), ncg);
|
||||
|
||||
}
|
||||
ncg.addChannel(nc);
|
||||
}
|
||||
ncg.addChannel(nc);
|
||||
} else {
|
||||
nonGrouped.addChannel(nc);
|
||||
}
|
||||
@@ -736,8 +738,29 @@ public class RankingHelper implements RankingConfig {
|
||||
return new ParceledListSlice<>(new ArrayList<>(groups.values()));
|
||||
}
|
||||
|
||||
public List<String> deleteNotificationChannelGroup(String pkg, int uid,
|
||||
String groupId) {
|
||||
List<String> deletedChannelIds = new ArrayList<>();
|
||||
Record r = getRecord(pkg, uid);
|
||||
if (r == null || TextUtils.isEmpty(groupId)) {
|
||||
return deletedChannelIds;
|
||||
}
|
||||
|
||||
r.groups.remove(groupId);
|
||||
|
||||
int N = r.channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel nc = r.channels.valueAt(i);
|
||||
if (groupId.equals(nc.getGroup())) {
|
||||
nc.setDeleted(true);
|
||||
deletedChannelIds.add(nc.getId());
|
||||
}
|
||||
}
|
||||
updateConfig();
|
||||
return deletedChannelIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@VisibleForTesting
|
||||
public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
|
||||
int uid) {
|
||||
Record r = getRecord(pkg, uid);
|
||||
|
||||
@@ -853,6 +853,43 @@ public class RankingHelperTest {
|
||||
assertEquals(1, mHelper.getNotificationChannels(pkg, uid, true).getList().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteGroup() throws Exception {
|
||||
NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
|
||||
NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted");
|
||||
NotificationChannel nonGroupedNonDeletedChannel =
|
||||
new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH);
|
||||
NotificationChannel groupedButNotDeleted =
|
||||
new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
|
||||
groupedButNotDeleted.setGroup("not");
|
||||
NotificationChannel groupedAndDeleted =
|
||||
new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT);
|
||||
groupedAndDeleted.setGroup("totally");
|
||||
|
||||
mHelper.createNotificationChannelGroup(pkg, uid, notDeleted, true);
|
||||
mHelper.createNotificationChannelGroup(pkg, uid, deleted, true);
|
||||
mHelper.createNotificationChannel(pkg, uid, nonGroupedNonDeletedChannel, true);
|
||||
mHelper.createNotificationChannel(pkg, uid, groupedAndDeleted, true);
|
||||
mHelper.createNotificationChannel(pkg, uid, groupedButNotDeleted, true);
|
||||
|
||||
mHelper.deleteNotificationChannelGroup(pkg, uid, deleted.getId());
|
||||
|
||||
assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), pkg, uid));
|
||||
assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), pkg, uid));
|
||||
|
||||
assertNull(mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), false));
|
||||
compareChannels(groupedAndDeleted,
|
||||
mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), true));
|
||||
|
||||
compareChannels(groupedButNotDeleted,
|
||||
mHelper.getNotificationChannel(pkg, uid, groupedButNotDeleted.getId(), false));
|
||||
compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
|
||||
pkg, uid, nonGroupedNonDeletedChannel.getId(), false));
|
||||
|
||||
// notDeleted
|
||||
assertEquals(1, mHelper.getNotificationChannelGroups(pkg, uid).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPackageChanged_packageRemoval() throws Exception {
|
||||
// Deleted
|
||||
@@ -889,7 +926,7 @@ public class RankingHelperTest {
|
||||
|
||||
mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
|
||||
|
||||
assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid, true).getList().size());
|
||||
assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user