• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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