| /* |
| * 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 static android.app.NotificationManager.IMPORTANCE_HIGH; |
| |
| import android.annotation.NonNull; |
| import android.app.NotificationChannel; |
| import android.app.NotificationChannelGroup; |
| import android.stats.sysui.NotificationEnums; |
| |
| 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, getLoggingImportance(channel)); |
| } |
| |
| /** |
| * 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, getLoggingImportance(channel), 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 oldLoggingImportance Previous logging 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 oldLoggingImportance, boolean byUser) { |
| logNotificationChannel(NotificationChannelEvent.getUpdated(byUser), |
| channel, uid, pkg, oldLoggingImportance, getLoggingImportance(channel)); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| /** |
| * Log blocking or unblocking of the entire app's notifications. |
| * @param uid UID of the app. |
| * @param pkg Package name of the app. |
| * @param enabled If true, notifications are now allowed. |
| */ |
| default void logAppNotificationsAllowed(int uid, String pkg, boolean enabled) { |
| logAppEvent(NotificationChannelEvent.getBlocked(enabled), uid, pkg); |
| } |
| |
| /** |
| * 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); |
| |
| /** |
| * Low-level interface for logging app-as-a-whole events, to be implemented. |
| * @param uid UID of app. |
| * @param pkg Package of app. |
| */ |
| void logAppEvent(@NonNull NotificationChannelEvent event, int uid, String pkg); |
| |
| /** |
| * 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), |
| @UiEvent(doc = "All notifications for the app were blocked.") |
| APP_NOTIFICATIONS_BLOCKED(557), |
| @UiEvent(doc = "Notifications for the app as a whole were unblocked.") |
| APP_NOTIFICATIONS_UNBLOCKED(558); |
| |
| 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; |
| } |
| |
| public static NotificationChannelEvent getBlocked(boolean enabled) { |
| return enabled ? APP_NOTIFICATIONS_UNBLOCKED : APP_NOTIFICATIONS_BLOCKED; |
| } |
| } |
| |
| /** |
| * @return Small hash of the channel ID, if present, or 0 otherwise. |
| */ |
| static int getIdHash(@NonNull NotificationChannel channel) { |
| return SmallHash.hash(channel.getId()); |
| } |
| |
| /** |
| * @return Small hash of the channel ID, if present, or 0 otherwise. |
| */ |
| static int getIdHash(@NonNull NotificationChannelGroup group) { |
| return SmallHash.hash(group.getId()); |
| } |
| |
| /** |
| * @return Logging importance for a channel: the regular importance, or |
| * IMPORTANCE_IMPORTANT_CONVERSATION for a HIGH-importance conversation tagged important. |
| */ |
| static int getLoggingImportance(@NonNull NotificationChannel channel) { |
| return getLoggingImportance(channel, channel.getImportance()); |
| } |
| |
| /** |
| * @return Logging importance for a channel or notification: the regular importance, or |
| * IMPORTANCE_IMPORTANT_CONVERSATION for a HIGH-importance conversation tagged important. |
| */ |
| static int getLoggingImportance(@NonNull NotificationChannel channel, int importance) { |
| if (channel.getConversationId() == null || importance < IMPORTANCE_HIGH) { |
| return importance; |
| } |
| return (channel.isImportantConversation()) |
| ? NotificationEnums.IMPORTANCE_IMPORTANT_CONVERSATION |
| : importance; |
| } |
| |
| /** |
| * @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; |
| } |
| |
| } |