Statsd-log notification channel changes.
Logs when a notification channel is created, substantially modified, or deleted. Channels are identified by app uid & package, and a small hash of the channel ID. Distinguishes user modifications from app modifications. Distinguishes conversation (system-created sub-channel) from regular channel create/delete. Bug: 146488473 Test: atest com.android.server.notification.PreferencesHelperTest Test: adb shell cmd stats print-logs && adb logcat -s statsd:I | grep ' (246)' Change-Id: Icf2b2707a69dc9d2fb5fa59d0033930e067f201b
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.server.notification;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
|
||||
/**
|
||||
* Interface for logging NotificationChannelModified statsd atoms. Provided as an interface to
|
||||
* enable unit-testing - use standard implementation NotificationChannelLoggerImpl in production.
|
||||
*/
|
||||
public interface NotificationChannelLogger {
|
||||
// The logging interface. Not anticipating a need to override these high-level methods, which by
|
||||
// default forward to a lower-level interface.
|
||||
|
||||
/**
|
||||
* Log the creation of a notification channel.
|
||||
* @param channel The channel.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
*/
|
||||
default void logNotificationChannelCreated(@NonNull NotificationChannel channel, int uid,
|
||||
String pkg) {
|
||||
logNotificationChannel(
|
||||
NotificationChannelEvent.getCreated(channel),
|
||||
channel, uid, pkg, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the deletion of a notification channel.
|
||||
* @param channel The channel.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
*/
|
||||
default void logNotificationChannelDeleted(@NonNull NotificationChannel channel, int uid,
|
||||
String pkg) {
|
||||
logNotificationChannel(
|
||||
NotificationChannelEvent.getDeleted(channel),
|
||||
channel, uid, pkg, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the modification of a notification channel.
|
||||
* @param channel The channel.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
* @param oldImportance Previous importance level of the channel.
|
||||
* @param byUser True if the modification was user-specified.
|
||||
*/
|
||||
default void logNotificationChannelModified(@NonNull NotificationChannel channel, int uid,
|
||||
String pkg, int oldImportance, boolean byUser) {
|
||||
logNotificationChannel(NotificationChannelEvent.getUpdated(byUser),
|
||||
channel, uid, pkg, oldImportance, channel.getImportance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the creation or modification of a notification channel group.
|
||||
* @param channelGroup The notification channel group.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
* @param isNew True if this is a creation of a new group.
|
||||
* @param wasBlocked
|
||||
*/
|
||||
default void logNotificationChannelGroup(@NonNull NotificationChannelGroup channelGroup,
|
||||
int uid, String pkg, boolean isNew, boolean wasBlocked) {
|
||||
logNotificationChannelGroup(NotificationChannelEvent.getGroupUpdated(isNew),
|
||||
channelGroup, uid, pkg, wasBlocked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the deletion of a notification channel group.
|
||||
* @param channelGroup The notification channel group.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
*/
|
||||
default void logNotificationChannelGroupDeleted(@NonNull NotificationChannelGroup channelGroup,
|
||||
int uid, String pkg) {
|
||||
logNotificationChannelGroup(NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_DELETED,
|
||||
channelGroup, uid, pkg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level interface for logging events, to be implemented.
|
||||
* @param event Event to log.
|
||||
* @param channel Notification channel.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
* @param oldImportance Old importance of the channel, if applicable (0 otherwise).
|
||||
* @param newImportance New importance of the channel, if applicable (0 otherwise).
|
||||
*/
|
||||
void logNotificationChannel(@NonNull NotificationChannelEvent event,
|
||||
@NonNull NotificationChannel channel, int uid, String pkg,
|
||||
int oldImportance, int newImportance);
|
||||
|
||||
/**
|
||||
* Low-level interface for logging channel group events, to be implemented.
|
||||
* @param event Event to log.
|
||||
* @param channelGroup Notification channel group.
|
||||
* @param uid UID of app that owns the channel.
|
||||
* @param pkg Package of app that owns the channel.
|
||||
* @param wasBlocked True if the channel is being modified and was previously blocked.
|
||||
*/
|
||||
void logNotificationChannelGroup(@NonNull NotificationChannelEvent event,
|
||||
@NonNull NotificationChannelGroup channelGroup, int uid, String pkg,
|
||||
boolean wasBlocked);
|
||||
|
||||
/**
|
||||
* The UiEvent enums that this class can log.
|
||||
*/
|
||||
enum NotificationChannelEvent implements UiEventLogger.UiEventEnum {
|
||||
@UiEvent(doc = "App created a new notification channel")
|
||||
NOTIFICATION_CHANNEL_CREATED(219),
|
||||
@UiEvent(doc = "App modified an existing notification channel")
|
||||
NOTIFICATION_CHANNEL_UPDATED(220),
|
||||
@UiEvent(doc = "User modified a new notification channel")
|
||||
NOTIFICATION_CHANNEL_UPDATED_BY_USER(221),
|
||||
@UiEvent(doc = "App deleted an existing notification channel")
|
||||
NOTIFICATION_CHANNEL_DELETED(222),
|
||||
@UiEvent(doc = "App created a new notification channel group")
|
||||
NOTIFICATION_CHANNEL_GROUP_CREATED(223),
|
||||
@UiEvent(doc = "App modified an existing notification channel group")
|
||||
NOTIFICATION_CHANNEL_GROUP_UPDATED(224),
|
||||
@UiEvent(doc = "App deleted an existing notification channel group")
|
||||
NOTIFICATION_CHANNEL_GROUP_DELETED(226),
|
||||
@UiEvent(doc = "System created a new conversation (sub-channel in a notification channel)")
|
||||
NOTIFICATION_CHANNEL_CONVERSATION_CREATED(272),
|
||||
@UiEvent(doc = "System deleted a new conversation (sub-channel in a notification channel)")
|
||||
NOTIFICATION_CHANNEL_CONVERSATION_DELETED(274);
|
||||
|
||||
|
||||
private final int mId;
|
||||
NotificationChannelEvent(int id) {
|
||||
mId = id;
|
||||
}
|
||||
@Override public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public static NotificationChannelEvent getUpdated(boolean byUser) {
|
||||
return byUser
|
||||
? NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER
|
||||
: NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED;
|
||||
}
|
||||
|
||||
public static NotificationChannelEvent getCreated(@NonNull NotificationChannel channel) {
|
||||
return channel.getConversationId() != null
|
||||
? NotificationChannelEvent.NOTIFICATION_CHANNEL_CONVERSATION_CREATED
|
||||
: NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED;
|
||||
}
|
||||
|
||||
public static NotificationChannelEvent getDeleted(@NonNull NotificationChannel channel) {
|
||||
return channel.getConversationId() != null
|
||||
? NotificationChannelEvent.NOTIFICATION_CHANNEL_CONVERSATION_DELETED
|
||||
: NotificationChannelEvent.NOTIFICATION_CHANNEL_DELETED;
|
||||
}
|
||||
|
||||
public static NotificationChannelEvent getGroupUpdated(boolean isNew) {
|
||||
return isNew
|
||||
? NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_CREATED
|
||||
: NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Small hash of the channel ID, if present, or 0 otherwise.
|
||||
*/
|
||||
static int getIdHash(@NonNull NotificationChannel channel) {
|
||||
return NotificationRecordLogger.smallHash(channel.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Small hash of the channel ID, if present, or 0 otherwise.
|
||||
*/
|
||||
static int getIdHash(@NonNull NotificationChannelGroup group) {
|
||||
return NotificationRecordLogger.smallHash(group.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return "Importance" for a channel group
|
||||
*/
|
||||
static int getImportance(@NonNull NotificationChannelGroup channelGroup) {
|
||||
return getImportance(channelGroup.isBlocked());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return "Importance" for a channel group, from its blocked status
|
||||
*/
|
||||
static int getImportance(boolean isBlocked) {
|
||||
return isBlocked
|
||||
? FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED__IMPORTANCE__IMPORTANCE_NONE
|
||||
: FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED__IMPORTANCE__IMPORTANCE_DEFAULT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.server.notification;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
|
||||
/**
|
||||
* Standard implementation of NotificationChannelLogger, which passes data through to StatsLog.
|
||||
* This layer is as skinny as possible, to maximize code coverage of unit tests. Nontrivial code
|
||||
* should live in the interface so it can be tested.
|
||||
*/
|
||||
public class NotificationChannelLoggerImpl implements NotificationChannelLogger {
|
||||
@Override
|
||||
public void logNotificationChannel(NotificationChannelEvent event,
|
||||
NotificationChannel channel, int uid, String pkg,
|
||||
int oldImportance, int newImportance) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED,
|
||||
/* int event_id*/ event.getId(),
|
||||
/* int uid*/ uid,
|
||||
/* String package_name */ pkg,
|
||||
/* int32 channel_id_hash */ NotificationChannelLogger.getIdHash(channel),
|
||||
/* int old_importance*/ oldImportance,
|
||||
/* int importance*/ newImportance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logNotificationChannelGroup(NotificationChannelEvent event,
|
||||
NotificationChannelGroup channelGroup, int uid, String pkg, boolean wasBlocked) {
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED,
|
||||
/* int event_id*/ event.getId(),
|
||||
/* int uid*/ uid,
|
||||
/* String package_name */ pkg,
|
||||
/* int32 channel_id_hash */ NotificationChannelLogger.getIdHash(channelGroup),
|
||||
/* int old_importance*/ NotificationChannelLogger.getImportance(wasBlocked),
|
||||
/* int importance*/ NotificationChannelLogger.getImportance(channelGroup));
|
||||
}
|
||||
}
|
||||
@@ -1979,7 +1979,8 @@ public class NotificationManagerService extends SystemService {
|
||||
mPreferencesHelper = new PreferencesHelper(getContext(),
|
||||
mPackageManagerClient,
|
||||
mRankingHandler,
|
||||
mZenModeHelper);
|
||||
mZenModeHelper,
|
||||
new NotificationChannelLoggerImpl());
|
||||
mRankingHelper = new RankingHelper(getContext(),
|
||||
mRankingHandler,
|
||||
mPreferencesHelper,
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.os.Bundle;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.NotificationStats;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
|
||||
@@ -307,27 +306,36 @@ public interface NotificationRecordLogger {
|
||||
* @return Small hash of the channel ID, if present, or 0 otherwise.
|
||||
*/
|
||||
int getChannelIdHash() {
|
||||
return smallHash(Objects.hashCode(r.getSbn().getNotification().getChannelId()));
|
||||
return smallHash(r.getSbn().getNotification().getChannelId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Small hash of the group ID, respecting group override if present. 0 otherwise.
|
||||
*/
|
||||
int getGroupIdHash() {
|
||||
return smallHash(Objects.hashCode(r.getSbn().getGroup()));
|
||||
return smallHash(r.getSbn().getGroup());
|
||||
}
|
||||
|
||||
// "Small" hashes will be in the range [0, MAX_HASH).
|
||||
static final int MAX_HASH = (1 << 13);
|
||||
|
||||
/**
|
||||
* Maps in to the range [0, MAX_HASH), keeping similar values distinct.
|
||||
* @param in An arbitrary integer.
|
||||
* @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static int smallHash(int in) {
|
||||
return Math.floorMod(in, MAX_HASH);
|
||||
}
|
||||
}
|
||||
|
||||
// "Small" hashes will be in the range [0, MAX_HASH).
|
||||
int MAX_HASH = (1 << 13);
|
||||
|
||||
/**
|
||||
* Maps in to the range [0, MAX_HASH), keeping similar values distinct.
|
||||
* @param in An arbitrary integer.
|
||||
* @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH).
|
||||
*/
|
||||
static int smallHash(int in) {
|
||||
return Math.floorMod(in, MAX_HASH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Small hash of the string, if non-null, or 0 otherwise.
|
||||
*/
|
||||
static int smallHash(@Nullable String in) {
|
||||
return smallHash(Objects.hashCode(in));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
private final PackageManager mPm;
|
||||
private final RankingHandler mRankingHandler;
|
||||
private final ZenModeHelper mZenModeHelper;
|
||||
private final NotificationChannelLogger mNotificationChannelLogger;
|
||||
|
||||
private SparseBooleanArray mBadgingEnabled;
|
||||
private boolean mBubblesEnabled = DEFAULT_ALLOW_BUBBLE;
|
||||
@@ -161,11 +162,12 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
|
||||
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
|
||||
ZenModeHelper zenHelper) {
|
||||
ZenModeHelper zenHelper, NotificationChannelLogger notificationChannelLogger) {
|
||||
mContext = context;
|
||||
mZenModeHelper = zenHelper;
|
||||
mRankingHandler = rankingHandler;
|
||||
mPm = pm;
|
||||
mNotificationChannelLogger = notificationChannelLogger;
|
||||
|
||||
// STOPSHIP (b/142218092) this should be removed before ship
|
||||
if (!wasBadgingForcedTrue(context)) {
|
||||
@@ -654,10 +656,6 @@ public class PreferencesHelper implements RankingConfig {
|
||||
throw new IllegalArgumentException("Invalid package");
|
||||
}
|
||||
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
|
||||
if (!group.equals(oldGroup)) {
|
||||
// will log for new entries as well as name/description changes
|
||||
MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
|
||||
}
|
||||
if (oldGroup != null) {
|
||||
group.setChannels(oldGroup.getChannels());
|
||||
|
||||
@@ -674,6 +672,13 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!group.equals(oldGroup)) {
|
||||
// will log for new entries as well as name/description changes
|
||||
MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
|
||||
mNotificationChannelLogger.logNotificationChannelGroup(group, uid, pkg,
|
||||
oldGroup == null,
|
||||
(oldGroup != null) && oldGroup.isBlocked());
|
||||
}
|
||||
r.groups.put(group.getId(), group);
|
||||
}
|
||||
}
|
||||
@@ -685,7 +690,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
Objects.requireNonNull(channel);
|
||||
Objects.requireNonNull(channel.getId());
|
||||
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
|
||||
boolean needsPolicyFileChange = false;
|
||||
boolean needsPolicyFileChange = false, wasUndeleted = false;
|
||||
synchronized (mPackagePreferences) {
|
||||
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
|
||||
if (r == null) {
|
||||
@@ -698,15 +703,18 @@ public class PreferencesHelper implements RankingConfig {
|
||||
throw new IllegalArgumentException("Reserved id");
|
||||
}
|
||||
NotificationChannel existing = r.channels.get(channel.getId());
|
||||
// Keep most of the existing settings
|
||||
if (existing != null && fromTargetApp) {
|
||||
// Actually modifying an existing channel - keep most of the existing settings
|
||||
if (existing.isDeleted()) {
|
||||
// The existing channel was deleted - undelete it.
|
||||
existing.setDeleted(false);
|
||||
needsPolicyFileChange = true;
|
||||
wasUndeleted = true;
|
||||
|
||||
// log a resurrected channel as if it's new again
|
||||
MetricsLogger.action(getChannelLog(channel, pkg).setType(
|
||||
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
|
||||
mNotificationChannelLogger.logNotificationChannelCreated(channel, uid, pkg);
|
||||
}
|
||||
|
||||
if (!Objects.equals(channel.getName().toString(), existing.getName().toString())) {
|
||||
@@ -756,6 +764,10 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
|
||||
updateConfig();
|
||||
if (needsPolicyFileChange && !wasUndeleted) {
|
||||
mNotificationChannelLogger.logNotificationChannelModified(existing, uid, pkg,
|
||||
previousExistingImportance, false);
|
||||
}
|
||||
return needsPolicyFileChange;
|
||||
}
|
||||
|
||||
@@ -806,6 +818,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
MetricsLogger.action(getChannelLog(channel, pkg).setType(
|
||||
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
|
||||
mNotificationChannelLogger.logNotificationChannelCreated(channel, uid, pkg);
|
||||
}
|
||||
|
||||
return needsPolicyFileChange;
|
||||
@@ -867,6 +880,8 @@ public class PreferencesHelper implements RankingConfig {
|
||||
// only log if there are real changes
|
||||
MetricsLogger.action(getChannelLog(updatedChannel, pkg)
|
||||
.setSubtype(fromUser ? 1 : 0));
|
||||
mNotificationChannelLogger.logNotificationChannelModified(updatedChannel, uid, pkg,
|
||||
channel.getImportance(), fromUser);
|
||||
}
|
||||
|
||||
if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
|
||||
@@ -954,14 +969,21 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
NotificationChannel channel = r.channels.get(channelId);
|
||||
if (channel != null) {
|
||||
channel.setDeleted(true);
|
||||
LogMaker lm = getChannelLog(channel, pkg);
|
||||
lm.setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
|
||||
MetricsLogger.action(lm);
|
||||
deleteNotificationChannelLocked(channel, pkg, uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
|
||||
updateChannelsBypassingDnd(mContext.getUserId());
|
||||
}
|
||||
private void deleteNotificationChannelLocked(NotificationChannel channel, String pkg, int uid) {
|
||||
if (!channel.isDeleted()) {
|
||||
channel.setDeleted(true);
|
||||
LogMaker lm = getChannelLog(channel, pkg);
|
||||
lm.setType(com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
|
||||
MetricsLogger.action(lm);
|
||||
mNotificationChannelLogger.logNotificationChannelDeleted(channel, uid, pkg);
|
||||
|
||||
if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
|
||||
updateChannelsBypassingDnd(mContext.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1158,13 +1180,17 @@ public class PreferencesHelper implements RankingConfig {
|
||||
return deletedChannels;
|
||||
}
|
||||
|
||||
r.groups.remove(groupId);
|
||||
NotificationChannelGroup channelGroup = r.groups.remove(groupId);
|
||||
if (channelGroup != null) {
|
||||
mNotificationChannelLogger.logNotificationChannelGroupDeleted(channelGroup, uid,
|
||||
pkg);
|
||||
}
|
||||
|
||||
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);
|
||||
deleteNotificationChannelLocked(nc, pkg, uid);
|
||||
deletedChannels.add(nc);
|
||||
}
|
||||
}
|
||||
@@ -1279,6 +1305,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
lm.setType(
|
||||
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_CLOSE);
|
||||
MetricsLogger.action(lm);
|
||||
mNotificationChannelLogger.logNotificationChannelDeleted(nc, uid, pkg);
|
||||
|
||||
deletedChannelIds.add(nc.getId());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.server.notification;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NotificationChannelLoggerFake implements NotificationChannelLogger {
|
||||
static class CallRecord {
|
||||
public NotificationChannelEvent event;
|
||||
CallRecord(NotificationChannelEvent event) {
|
||||
this.event = event;
|
||||
}
|
||||
}
|
||||
|
||||
private List<CallRecord> mCalls = new ArrayList<>();
|
||||
|
||||
List<CallRecord> getCalls() {
|
||||
return mCalls;
|
||||
}
|
||||
|
||||
CallRecord get(int index) {
|
||||
return mCalls.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logNotificationChannel(NotificationChannelEvent event, NotificationChannel channel,
|
||||
int uid, String pkg, int oldImportance, int newImportance) {
|
||||
mCalls.add(new CallRecord(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logNotificationChannelGroup(NotificationChannelEvent event,
|
||||
NotificationChannelGroup channelGroup, int uid, String pkg, boolean wasBlocked) {
|
||||
mCalls.add(new CallRecord(event));
|
||||
}
|
||||
}
|
||||
@@ -60,16 +60,16 @@ public class NotificationRecordLoggerTest extends UiServiceTestCase {
|
||||
|
||||
@Test
|
||||
public void testSmallHash() {
|
||||
assertEquals(0, NotificationRecordLogger.NotificationRecordPair.smallHash(0));
|
||||
final int maxHash = NotificationRecordLogger.NotificationRecordPair.MAX_HASH;
|
||||
assertEquals(0, NotificationRecordLogger.smallHash(0));
|
||||
final int maxHash = NotificationRecordLogger.MAX_HASH;
|
||||
assertEquals(0,
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(maxHash));
|
||||
NotificationRecordLogger.smallHash(maxHash));
|
||||
assertEquals(0,
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(17 * maxHash));
|
||||
NotificationRecordLogger.smallHash(17 * maxHash));
|
||||
assertEquals(maxHash - 1,
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(maxHash - 1));
|
||||
NotificationRecordLogger.smallHash(maxHash - 1));
|
||||
assertEquals(maxHash - 1,
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(-1));
|
||||
NotificationRecordLogger.smallHash(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -78,10 +78,10 @@ public class NotificationRecordLoggerTest extends UiServiceTestCase {
|
||||
getNotificationRecordPair(0, null).getNotificationIdHash());
|
||||
assertEquals(1,
|
||||
getNotificationRecordPair(1, null).getNotificationIdHash());
|
||||
assertEquals(NotificationRecordLogger.NotificationRecordPair.MAX_HASH - 1,
|
||||
assertEquals(NotificationRecordLogger.MAX_HASH - 1,
|
||||
getNotificationRecordPair(-1, null).getNotificationIdHash());
|
||||
final String tag = "someTag";
|
||||
final int hash = NotificationRecordLogger.NotificationRecordPair.smallHash(tag.hashCode());
|
||||
final int hash = NotificationRecordLogger.smallHash(tag.hashCode());
|
||||
assertEquals(hash, getNotificationRecordPair(0, tag).getNotificationIdHash());
|
||||
// We xor the tag and hashcode together before compressing the range. The order of
|
||||
// operations doesn't matter if id is small.
|
||||
@@ -89,19 +89,19 @@ public class NotificationRecordLoggerTest extends UiServiceTestCase {
|
||||
getNotificationRecordPair(1, tag).getNotificationIdHash());
|
||||
// But it does matter for an id with more 1 bits than fit in the small hash.
|
||||
assertEquals(
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(-1 ^ tag.hashCode()),
|
||||
NotificationRecordLogger.smallHash(-1 ^ tag.hashCode()),
|
||||
getNotificationRecordPair(-1, tag).getNotificationIdHash());
|
||||
assertNotEquals(-1 ^ hash,
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(-1 ^ tag.hashCode()));
|
||||
NotificationRecordLogger.smallHash(-1 ^ tag.hashCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetChannelIdHash() {
|
||||
assertEquals(
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(CHANNEL_ID.hashCode()),
|
||||
NotificationRecordLogger.smallHash(CHANNEL_ID.hashCode()),
|
||||
getNotificationRecordPair(0, null).getChannelIdHash());
|
||||
assertNotEquals(
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(CHANNEL_ID.hashCode()),
|
||||
NotificationRecordLogger.smallHash(CHANNEL_ID.hashCode()),
|
||||
CHANNEL_ID.hashCode());
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class NotificationRecordLoggerTest extends UiServiceTestCase {
|
||||
final String group = "someGroup";
|
||||
p.r.setOverrideGroupKey(group);
|
||||
assertEquals(
|
||||
NotificationRecordLogger.NotificationRecordPair.smallHash(group.hashCode()),
|
||||
NotificationRecordLogger.smallHash(group.hashCode()),
|
||||
p.getGroupIdHash());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
|
||||
private PreferencesHelper mHelper;
|
||||
private AudioAttributes mAudioAttributes;
|
||||
private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -183,7 +184,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
|
||||
NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
|
||||
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
resetZenModeHelper();
|
||||
|
||||
mAudioAttributes = new AudioAttributes.Builder()
|
||||
@@ -1106,6 +1107,22 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, "does not exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleDeleteChannel() throws Exception {
|
||||
NotificationChannel channel = getChannel();
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
|
||||
mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
|
||||
mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId());
|
||||
assertEquals(2, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED,
|
||||
mLogger.get(0).event);
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_DELETED,
|
||||
mLogger.get(1).event);
|
||||
// No log for the second delete of the same channel.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeletedChannel() throws Exception {
|
||||
NotificationChannel channel = getChannel();
|
||||
@@ -1444,7 +1461,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
|
||||
NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
|
||||
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
assertFalse(mHelper.areChannelsBypassingDnd());
|
||||
verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
|
||||
resetZenModeHelper();
|
||||
@@ -1455,7 +1472,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
// start notification policy off with mAreChannelsBypassingDnd = false
|
||||
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0);
|
||||
when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
assertFalse(mHelper.areChannelsBypassingDnd());
|
||||
verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
|
||||
resetZenModeHelper();
|
||||
@@ -1525,6 +1542,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
// Old settings not overridden
|
||||
compareChannels(channel,
|
||||
mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false));
|
||||
|
||||
assertEquals(1, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED,
|
||||
mLogger.get(0).event);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1594,6 +1616,16 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertEquals(1, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).size());
|
||||
|
||||
verify(mHandler, never()).requestSort();
|
||||
|
||||
assertEquals(7, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_GROUP_DELETED,
|
||||
mLogger.get(5).event); // Next-to-last log is the deletion of the channel group.
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_DELETED,
|
||||
mLogger.get(6).event); // Final log is the deletion of the channel.
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1739,6 +1771,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertEquals(ncg,
|
||||
mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next());
|
||||
verify(mHandler, never()).requestSort();
|
||||
assertEquals(1, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_GROUP_CREATED,
|
||||
mLogger.get(0).event);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1751,6 +1788,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
fail("Created a channel with a bad group");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
assertEquals(0, mLogger.getCalls().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1905,6 +1943,17 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
|
||||
|
||||
verify(mHandler, times(1)).requestSort();
|
||||
assertEquals(3, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_GROUP_CREATED,
|
||||
mLogger.get(0).event);
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED,
|
||||
mLogger.get(1).event);
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED,
|
||||
mLogger.get(2).event);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2189,7 +2238,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "</ranking>\n";
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadByteArrayXml(preQXml.getBytes(), true, UserHandle.USER_SYSTEM);
|
||||
|
||||
assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
|
||||
@@ -2201,7 +2250,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.setHideSilentStatusIcons(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
|
||||
@@ -2297,7 +2346,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_UNSPECIFIED);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
|
||||
@@ -2308,7 +2357,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
|
||||
@@ -2320,7 +2369,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.revokeNotificationDelegate(PKG_O, UID_O);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
|
||||
@@ -2332,7 +2381,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
// appears disabled
|
||||
@@ -2350,7 +2399,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.revokeNotificationDelegate(PKG_O, UID_O);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
// appears disabled
|
||||
@@ -2368,7 +2417,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertTrue(mHelper.areBubblesAllowed(PKG_O, UID_O));
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertTrue(mHelper.areBubblesAllowed(PKG_O, UID_O));
|
||||
@@ -2383,7 +2432,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
mHelper.getAppLockedFields(PKG_O, UID_O));
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
loadStreamXml(baos, false, UserHandle.USER_ALL);
|
||||
|
||||
assertFalse(mHelper.areBubblesAllowed(PKG_O, UID_O));
|
||||
@@ -2876,7 +2925,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
public void testPlaceholderConversationId_flagOn() throws Exception {
|
||||
Settings.Global.putString(
|
||||
mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
|
||||
final String xml = "<ranking version=\"1\">\n"
|
||||
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
|
||||
@@ -2896,7 +2945,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
public void testPlaceholderConversationId_flagOff() throws Exception {
|
||||
Settings.Global.putString(
|
||||
mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
|
||||
final String xml = "<ranking version=\"1\">\n"
|
||||
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
|
||||
@@ -2916,7 +2965,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
public void testNormalConversationId_flagOff() throws Exception {
|
||||
Settings.Global.putString(
|
||||
mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
|
||||
final String xml = "<ranking version=\"1\">\n"
|
||||
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
|
||||
@@ -2936,7 +2985,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
public void testNoConversationId_flagOff() throws Exception {
|
||||
Settings.Global.putString(
|
||||
mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
|
||||
|
||||
final String xml = "<ranking version=\"1\">\n"
|
||||
+ "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
|
||||
@@ -3171,5 +3220,33 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertEquals(channel, mHelper.getNotificationChannel(PKG_O, UID_O, channel.getId(), true));
|
||||
assertEquals(channel2,
|
||||
mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), true));
|
||||
|
||||
assertEquals(7, mLogger.getCalls().size());
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED,
|
||||
mLogger.get(0).event); // Channel messages
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED,
|
||||
mLogger.get(1).event); // Channel calls
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_CONVERSATION_CREATED,
|
||||
mLogger.get(2).event); // Channel channel - Conversation A person msgs
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_CONVERSATION_CREATED,
|
||||
mLogger.get(3).event); // Channel noMatch - Conversation B person msgs
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_CONVERSATION_CREATED,
|
||||
mLogger.get(4).event); // Channel channel2 - Conversation A person calls
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_CONVERSATION_DELETED,
|
||||
mLogger.get(5).event); // Delete Channel channel - Conversation A person msgs
|
||||
assertEquals(
|
||||
NotificationChannelLogger.NotificationChannelEvent
|
||||
.NOTIFICATION_CHANNEL_CONVERSATION_DELETED,
|
||||
mLogger.get(6).event); // Delete Channel channel2 - Conversation A person calls
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user