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.systemui.statusbar.notification.logging; 18 19 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING; 20 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE; 21 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_HEADS_UP; 22 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS; 23 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_NEWS; 24 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE; 25 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PRIORITY_PEOPLE; 26 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PROMO; 27 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_RECS; 28 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT; 29 import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SOCIAL; 30 31 import android.annotation.Nullable; 32 import android.service.notification.StatusBarNotification; 33 34 import com.android.internal.logging.UiEvent; 35 import com.android.internal.logging.UiEventLogger; 36 import com.android.systemui.statusbar.notification.collection.EntryAdapter; 37 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 38 import com.android.systemui.statusbar.notification.logging.nano.Notifications; 39 import com.android.systemui.statusbar.notification.stack.PriorityBucket; 40 41 import java.util.List; 42 43 /** 44 * Statsd logging for notification panel. 45 */ 46 public interface NotificationPanelLogger { 47 48 /** 49 * Log a NOTIFICATION_PANEL_REPORTED statsd event. 50 */ logPanelShown(boolean isLockscreen, Notifications.NotificationList proto)51 void logPanelShown(boolean isLockscreen, Notifications.NotificationList proto); 52 53 /** 54 * Log a NOTIFICATION_PANEL_REPORTED statsd event. 55 * @param visibleNotifications as provided by NotificationEntryManager.getVisibleNotifications() 56 */ logPanelShown(boolean isLockscreen, @Nullable List<NotificationEntry> visibleNotifications)57 void logPanelShown(boolean isLockscreen, 58 @Nullable List<NotificationEntry> visibleNotifications); 59 60 /** 61 * Log a NOTIFICATION_PANEL_REPORTED statsd event, with 62 * {@link NotificationPanelEvent#NOTIFICATION_DRAG} as the eventID. 63 * 64 * @param draggedNotification the notification that is being dragged 65 */ logNotificationDrag(NotificationEntry draggedNotification)66 void logNotificationDrag(NotificationEntry draggedNotification); 67 logNotificationDrag(EntryAdapter draggedNotification)68 void logNotificationDrag(EntryAdapter draggedNotification); 69 70 enum NotificationPanelEvent implements UiEventLogger.UiEventEnum { 71 @UiEvent(doc = "Notification panel shown from status bar.") 72 NOTIFICATION_PANEL_OPEN_STATUS_BAR(200), 73 @UiEvent(doc = "Notification panel shown from lockscreen.") 74 NOTIFICATION_PANEL_OPEN_LOCKSCREEN(201), 75 @UiEvent(doc = "Notification was dragged") 76 NOTIFICATION_DRAG(1226); 77 78 private final int mId; NotificationPanelEvent(int id)79 NotificationPanelEvent(int id) { 80 mId = id; 81 } getId()82 @Override public int getId() { 83 return mId; 84 } 85 fromLockscreen(boolean isLockscreen)86 public static NotificationPanelEvent fromLockscreen(boolean isLockscreen) { 87 return isLockscreen ? NOTIFICATION_PANEL_OPEN_LOCKSCREEN : 88 NOTIFICATION_PANEL_OPEN_STATUS_BAR; 89 } 90 } 91 92 /** 93 * Composes a NotificationsList proto from the list of visible notifications. 94 * @param visibleNotifications as provided by NotificationEntryManager.getVisibleNotifications() 95 * @return NotificationList proto suitable for SysUiStatsLog.write(NOTIFICATION_PANEL_REPORTED) 96 */ toNotificationProto( @ullable List<NotificationEntry> visibleNotifications)97 static Notifications.NotificationList toNotificationProto( 98 @Nullable List<NotificationEntry> visibleNotifications) { 99 Notifications.NotificationList notificationList = new Notifications.NotificationList(); 100 if (visibleNotifications == null) { 101 return notificationList; 102 } 103 final Notifications.Notification[] proto_array = 104 new Notifications.Notification[visibleNotifications.size()]; 105 int i = 0; 106 for (NotificationEntry ne : visibleNotifications) { 107 final StatusBarNotification n = ne.getSbn(); 108 if (n != null) { 109 final Notifications.Notification proto = new Notifications.Notification(); 110 proto.uid = n.getUid(); 111 proto.packageName = n.getPackageName(); 112 if (n.getInstanceId() != null) { 113 proto.instanceId = n.getInstanceId().getId(); 114 } 115 // TODO set np.groupInstanceId 116 if (n.getNotification() != null) { 117 proto.isGroupSummary = n.getNotification().isGroupSummary(); 118 } 119 proto.section = toNotificationSection(ne.getBucket()); 120 proto_array[i] = proto; 121 } 122 ++i; 123 } 124 notificationList.notifications = proto_array; 125 return notificationList; 126 } 127 128 /** 129 * Composes a NotificationsList proto from the list of visible notifications. 130 * @param visibleNotifications as provided by NotificationEntryManager.getVisibleNotifications() 131 * @return NotificationList proto suitable for SysUiStatsLog.write(NOTIFICATION_PANEL_REPORTED) 132 */ adapterToNotificationProto( @ullable List<EntryAdapter> visibleNotifications)133 static Notifications.NotificationList adapterToNotificationProto( 134 @Nullable List<EntryAdapter> visibleNotifications) { 135 Notifications.NotificationList notificationList = new Notifications.NotificationList(); 136 if (visibleNotifications == null) { 137 return notificationList; 138 } 139 final Notifications.Notification[] proto_array = 140 new Notifications.Notification[visibleNotifications.size()]; 141 int i = 0; 142 for (EntryAdapter ne : visibleNotifications) { 143 final StatusBarNotification n = ne.getSbn(); 144 if (n != null) { 145 final Notifications.Notification proto = new Notifications.Notification(); 146 proto.uid = n.getUid(); 147 proto.packageName = n.getPackageName(); 148 if (n.getInstanceId() != null) { 149 proto.instanceId = n.getInstanceId().getId(); 150 } 151 // TODO set np.groupInstanceId 152 if (n.getNotification() != null) { 153 proto.isGroupSummary = n.getNotification().isGroupSummary(); 154 } 155 proto.section = toNotificationSection(ne.getSectionBucket()); 156 proto_array[i] = proto; 157 } 158 ++i; 159 } 160 notificationList.notifications = proto_array; 161 return notificationList; 162 } 163 164 /** 165 * Maps PriorityBucket enum to Notification.SECTION constant. The two lists should generally 166 * use matching names, but the values may differ, because PriorityBucket order changes from 167 * time to time, while logs need to have stable meanings. 168 * @param bucket PriorityBucket constant 169 * @return Notification.SECTION constant 170 */ toNotificationSection(@riorityBucket int bucket)171 static int toNotificationSection(@PriorityBucket int bucket) { 172 switch(bucket) { 173 case BUCKET_MEDIA_CONTROLS : return Notifications.Notification.SECTION_MEDIA_CONTROLS; 174 case BUCKET_HEADS_UP: return Notifications.Notification.SECTION_HEADS_UP; 175 case BUCKET_FOREGROUND_SERVICE: 176 return Notifications.Notification.SECTION_FOREGROUND_SERVICE; 177 case BUCKET_PEOPLE, BUCKET_PRIORITY_PEOPLE: 178 return Notifications.Notification.SECTION_PEOPLE; 179 case BUCKET_ALERTING: return Notifications.Notification.SECTION_ALERTING; 180 case BUCKET_SILENT: return Notifications.Notification.SECTION_SILENT; 181 case BUCKET_NEWS: return Notifications.Notification.SECTION_NEWS; 182 case BUCKET_SOCIAL: return Notifications.Notification.SECTION_SOCIAL; 183 case BUCKET_RECS: return Notifications.Notification.SECTION_RECS; 184 case BUCKET_PROMO: return Notifications.Notification.SECTION_PROMO; 185 } 186 return Notifications.Notification.SECTION_UNKNOWN; 187 } 188 189 } 190