1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.notification; 18 19 import static android.app.NotificationManager.IMPORTANCE_HIGH; 20 21 import android.annotation.NonNull; 22 import android.app.NotificationChannel; 23 import android.app.NotificationChannelGroup; 24 import android.stats.sysui.NotificationEnums; 25 26 import com.android.internal.logging.UiEvent; 27 import com.android.internal.logging.UiEventLogger; 28 import com.android.internal.util.FrameworkStatsLog; 29 30 /** 31 * Interface for logging NotificationChannelModified statsd atoms. Provided as an interface to 32 * enable unit-testing - use standard implementation NotificationChannelLoggerImpl in production. 33 */ 34 public interface NotificationChannelLogger { 35 // The logging interface. Not anticipating a need to override these high-level methods, which by 36 // default forward to a lower-level interface. 37 38 /** 39 * Log the creation of a notification channel. 40 * @param channel The channel. 41 * @param uid UID of app that owns the channel. 42 * @param pkg Package of app that owns the channel. 43 */ logNotificationChannelCreated(@onNull NotificationChannel channel, int uid, String pkg)44 default void logNotificationChannelCreated(@NonNull NotificationChannel channel, int uid, 45 String pkg) { 46 logNotificationChannel( 47 NotificationChannelEvent.getCreated(channel), 48 channel, uid, pkg, 0, getLoggingImportance(channel)); 49 } 50 51 /** 52 * Log the deletion of a notification channel. 53 * @param channel The channel. 54 * @param uid UID of app that owns the channel. 55 * @param pkg Package of app that owns the channel. 56 */ logNotificationChannelDeleted(@onNull NotificationChannel channel, int uid, String pkg)57 default void logNotificationChannelDeleted(@NonNull NotificationChannel channel, int uid, 58 String pkg) { 59 logNotificationChannel( 60 NotificationChannelEvent.getDeleted(channel), 61 channel, uid, pkg, getLoggingImportance(channel), 0); 62 } 63 64 /** 65 * Log the modification of a notification channel. 66 * @param channel The channel. 67 * @param uid UID of app that owns the channel. 68 * @param pkg Package of app that owns the channel. 69 * @param oldLoggingImportance Previous logging importance level of the channel. 70 * @param byUser True if the modification was user-specified. 71 */ logNotificationChannelModified(@onNull NotificationChannel channel, int uid, String pkg, int oldLoggingImportance, boolean byUser)72 default void logNotificationChannelModified(@NonNull NotificationChannel channel, int uid, 73 String pkg, int oldLoggingImportance, boolean byUser) { 74 logNotificationChannel(NotificationChannelEvent.getUpdated(byUser), 75 channel, uid, pkg, oldLoggingImportance, getLoggingImportance(channel)); 76 } 77 78 /** 79 * Log the creation or modification of a notification channel group. 80 * @param channelGroup The notification channel group. 81 * @param uid UID of app that owns the channel. 82 * @param pkg Package of app that owns the channel. 83 * @param isNew True if this is a creation of a new group. 84 * @param wasBlocked 85 */ logNotificationChannelGroup(@onNull NotificationChannelGroup channelGroup, int uid, String pkg, boolean isNew, boolean wasBlocked)86 default void logNotificationChannelGroup(@NonNull NotificationChannelGroup channelGroup, 87 int uid, String pkg, boolean isNew, boolean wasBlocked) { 88 logNotificationChannelGroup(NotificationChannelEvent.getGroupUpdated(isNew), 89 channelGroup, uid, pkg, wasBlocked); 90 } 91 92 /** 93 * Log the deletion of a notification channel group. 94 * @param channelGroup The notification channel group. 95 * @param uid UID of app that owns the channel. 96 * @param pkg Package of app that owns the channel. 97 */ logNotificationChannelGroupDeleted(@onNull NotificationChannelGroup channelGroup, int uid, String pkg)98 default void logNotificationChannelGroupDeleted(@NonNull NotificationChannelGroup channelGroup, 99 int uid, String pkg) { 100 logNotificationChannelGroup(NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_DELETED, 101 channelGroup, uid, pkg, false); 102 } 103 104 /** 105 * Log blocking or unblocking of the entire app's notifications. 106 * @param uid UID of the app. 107 * @param pkg Package name of the app. 108 * @param enabled If true, notifications are now allowed. 109 */ logAppNotificationsAllowed(int uid, String pkg, boolean enabled)110 default void logAppNotificationsAllowed(int uid, String pkg, boolean enabled) { 111 logAppEvent(NotificationChannelEvent.getBlocked(enabled), uid, pkg); 112 } 113 114 /** 115 * Low-level interface for logging events, to be implemented. 116 * @param event Event to log. 117 * @param channel Notification channel. 118 * @param uid UID of app that owns the channel. 119 * @param pkg Package of app that owns the channel. 120 * @param oldImportance Old importance of the channel, if applicable (0 otherwise). 121 * @param newImportance New importance of the channel, if applicable (0 otherwise). 122 */ logNotificationChannel(@onNull NotificationChannelEvent event, @NonNull NotificationChannel channel, int uid, String pkg, int oldImportance, int newImportance)123 void logNotificationChannel(@NonNull NotificationChannelEvent event, 124 @NonNull NotificationChannel channel, int uid, String pkg, 125 int oldImportance, int newImportance); 126 127 /** 128 * Low-level interface for logging channel group events, to be implemented. 129 * @param event Event to log. 130 * @param channelGroup Notification channel group. 131 * @param uid UID of app that owns the channel. 132 * @param pkg Package of app that owns the channel. 133 * @param wasBlocked True if the channel is being modified and was previously blocked. 134 */ logNotificationChannelGroup(@onNull NotificationChannelEvent event, @NonNull NotificationChannelGroup channelGroup, int uid, String pkg, boolean wasBlocked)135 void logNotificationChannelGroup(@NonNull NotificationChannelEvent event, 136 @NonNull NotificationChannelGroup channelGroup, int uid, String pkg, 137 boolean wasBlocked); 138 139 /** 140 * Low-level interface for logging app-as-a-whole events, to be implemented. 141 * @param uid UID of app. 142 * @param pkg Package of app. 143 */ logAppEvent(@onNull NotificationChannelEvent event, int uid, String pkg)144 void logAppEvent(@NonNull NotificationChannelEvent event, int uid, String pkg); 145 146 /** 147 * The UiEvent enums that this class can log. 148 */ 149 enum NotificationChannelEvent implements UiEventLogger.UiEventEnum { 150 @UiEvent(doc = "App created a new notification channel") 151 NOTIFICATION_CHANNEL_CREATED(219), 152 @UiEvent(doc = "App modified an existing notification channel") 153 NOTIFICATION_CHANNEL_UPDATED(220), 154 @UiEvent(doc = "User modified a new notification channel") 155 NOTIFICATION_CHANNEL_UPDATED_BY_USER(221), 156 @UiEvent(doc = "App deleted an existing notification channel") 157 NOTIFICATION_CHANNEL_DELETED(222), 158 @UiEvent(doc = "App created a new notification channel group") 159 NOTIFICATION_CHANNEL_GROUP_CREATED(223), 160 @UiEvent(doc = "App modified an existing notification channel group") 161 NOTIFICATION_CHANNEL_GROUP_UPDATED(224), 162 @UiEvent(doc = "App deleted an existing notification channel group") 163 NOTIFICATION_CHANNEL_GROUP_DELETED(226), 164 @UiEvent(doc = "System created a new conversation (sub-channel in a notification channel)") 165 NOTIFICATION_CHANNEL_CONVERSATION_CREATED(272), 166 @UiEvent(doc = "System deleted a new conversation (sub-channel in a notification channel)") 167 NOTIFICATION_CHANNEL_CONVERSATION_DELETED(274), 168 @UiEvent(doc = "All notifications for the app were blocked.") 169 APP_NOTIFICATIONS_BLOCKED(557), 170 @UiEvent(doc = "Notifications for the app as a whole were unblocked.") 171 APP_NOTIFICATIONS_UNBLOCKED(558); 172 173 private final int mId; NotificationChannelEvent(int id)174 NotificationChannelEvent(int id) { 175 mId = id; 176 } getId()177 @Override public int getId() { 178 return mId; 179 } 180 getUpdated(boolean byUser)181 public static NotificationChannelEvent getUpdated(boolean byUser) { 182 return byUser 183 ? NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER 184 : NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED; 185 } 186 getCreated(@onNull NotificationChannel channel)187 public static NotificationChannelEvent getCreated(@NonNull NotificationChannel channel) { 188 return channel.getConversationId() != null 189 ? NotificationChannelEvent.NOTIFICATION_CHANNEL_CONVERSATION_CREATED 190 : NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED; 191 } 192 getDeleted(@onNull NotificationChannel channel)193 public static NotificationChannelEvent getDeleted(@NonNull NotificationChannel channel) { 194 return channel.getConversationId() != null 195 ? NotificationChannelEvent.NOTIFICATION_CHANNEL_CONVERSATION_DELETED 196 : NotificationChannelEvent.NOTIFICATION_CHANNEL_DELETED; 197 } 198 getGroupUpdated(boolean isNew)199 public static NotificationChannelEvent getGroupUpdated(boolean isNew) { 200 return isNew 201 ? NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_CREATED 202 : NotificationChannelEvent.NOTIFICATION_CHANNEL_GROUP_DELETED; 203 } 204 getBlocked(boolean enabled)205 public static NotificationChannelEvent getBlocked(boolean enabled) { 206 return enabled ? APP_NOTIFICATIONS_UNBLOCKED : APP_NOTIFICATIONS_BLOCKED; 207 } 208 } 209 210 /** 211 * @return Small hash of the channel ID, if present, or 0 otherwise. 212 */ getIdHash(@onNull NotificationChannel channel)213 static int getIdHash(@NonNull NotificationChannel channel) { 214 return SmallHash.hash(channel.getId()); 215 } 216 217 /** 218 * @return Small hash of the conversation ID, if present, or 0 otherwise. 219 */ getConversationIdHash(@onNull NotificationChannel channel)220 static int getConversationIdHash(@NonNull NotificationChannel channel) { 221 return SmallHash.hash(channel.getConversationId()); 222 } 223 224 /** 225 * @return Small hash of the channel ID, if present, or 0 otherwise. 226 */ getIdHash(@onNull NotificationChannelGroup group)227 static int getIdHash(@NonNull NotificationChannelGroup group) { 228 return SmallHash.hash(group.getId()); 229 } 230 231 /** 232 * @return Logging importance for a channel: the regular importance, or 233 * IMPORTANCE_IMPORTANT_CONVERSATION for a HIGH-importance conversation tagged important. 234 */ getLoggingImportance(@onNull NotificationChannel channel)235 static int getLoggingImportance(@NonNull NotificationChannel channel) { 236 return getLoggingImportance(channel, channel.getImportance()); 237 } 238 239 /** 240 * @return Logging importance for a channel or notification: the regular importance, or 241 * IMPORTANCE_IMPORTANT_CONVERSATION for a HIGH-importance conversation tagged important. 242 */ getLoggingImportance(@onNull NotificationChannel channel, int importance)243 static int getLoggingImportance(@NonNull NotificationChannel channel, int importance) { 244 if (channel.getConversationId() == null || importance < IMPORTANCE_HIGH) { 245 return importance; 246 } 247 return (channel.isImportantConversation()) 248 ? NotificationEnums.IMPORTANCE_IMPORTANT_CONVERSATION 249 : importance; 250 } 251 252 /** 253 * @return "Importance" for a channel group 254 */ getImportance(@onNull NotificationChannelGroup channelGroup)255 static int getImportance(@NonNull NotificationChannelGroup channelGroup) { 256 return getImportance(channelGroup.isBlocked()); 257 } 258 259 /** 260 * @return "Importance" for a channel group, from its blocked status 261 */ getImportance(boolean isBlocked)262 static int getImportance(boolean isBlocked) { 263 return isBlocked 264 ? FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED__IMPORTANCE__IMPORTANCE_NONE 265 : FrameworkStatsLog.NOTIFICATION_CHANNEL_MODIFIED__IMPORTANCE__IMPORTANCE_DEFAULT; 266 } 267 268 } 269