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.wm.shell.bubbles; 18 19 import com.android.internal.annotations.VisibleForTesting; 20 import com.android.internal.logging.UiEvent; 21 import com.android.internal.logging.UiEventLogger; 22 import com.android.internal.util.FrameworkStatsLog; 23 24 /** 25 * Implementation of UiEventLogger for logging bubble UI events. 26 * 27 * See UiEventReported atom in atoms.proto for more context. 28 */ 29 public class BubbleLogger { 30 31 private final UiEventLogger mUiEventLogger; 32 33 /** 34 * Bubble UI event. 35 */ 36 @VisibleForTesting 37 public enum Event implements UiEventLogger.UiEventEnum { 38 39 @UiEvent(doc = "User dismissed the bubble via gesture, add bubble to overflow.") 40 BUBBLE_OVERFLOW_ADD_USER_GESTURE(483), 41 42 @UiEvent(doc = "No more space in top row, add bubble to overflow.") 43 BUBBLE_OVERFLOW_ADD_AGED(484), 44 45 @UiEvent(doc = "No more space in overflow, remove bubble from overflow") 46 BUBBLE_OVERFLOW_REMOVE_MAX_REACHED(485), 47 48 @UiEvent(doc = "Notification canceled, remove bubble from overflow.") 49 BUBBLE_OVERFLOW_REMOVE_CANCEL(486), 50 51 @UiEvent(doc = "Notification group canceled, remove bubble for child notif from overflow.") 52 BUBBLE_OVERFLOW_REMOVE_GROUP_CANCEL(487), 53 54 @UiEvent(doc = "Notification no longer bubble, remove bubble from overflow.") 55 BUBBLE_OVERFLOW_REMOVE_NO_LONGER_BUBBLE(488), 56 57 @UiEvent(doc = "User tapped overflow bubble. Promote bubble back to top row.") 58 BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK(489), 59 60 @UiEvent(doc = "User blocked notification from bubbling, remove bubble from overflow.") 61 BUBBLE_OVERFLOW_REMOVE_BLOCKED(490), 62 63 @UiEvent(doc = "User selected the overflow.") 64 BUBBLE_OVERFLOW_SELECTED(600), 65 66 @UiEvent(doc = "Restore bubble to overflow after phone reboot.") 67 BUBBLE_OVERFLOW_RECOVER(691); 68 69 private final int mId; 70 Event(int id)71 Event(int id) { 72 mId = id; 73 } 74 75 @Override getId()76 public int getId() { 77 return mId; 78 } 79 } 80 BubbleLogger(UiEventLogger uiEventLogger)81 public BubbleLogger(UiEventLogger uiEventLogger) { 82 mUiEventLogger = uiEventLogger; 83 } 84 85 /** 86 * @param b Bubble involved in this UI event 87 * @param e UI event 88 */ log(Bubble b, UiEventLogger.UiEventEnum e)89 public void log(Bubble b, UiEventLogger.UiEventEnum e) { 90 mUiEventLogger.logWithInstanceId(e, b.getAppUid(), b.getPackageName(), b.getInstanceId()); 91 } 92 93 /** 94 * @param b Bubble removed from overflow 95 * @param r Reason that bubble was removed 96 */ logOverflowRemove(Bubble b, @Bubbles.DismissReason int r)97 public void logOverflowRemove(Bubble b, @Bubbles.DismissReason int r) { 98 if (r == Bubbles.DISMISS_NOTIF_CANCEL) { 99 log(b, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_CANCEL); 100 } else if (r == Bubbles.DISMISS_GROUP_CANCELLED) { 101 log(b, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_GROUP_CANCEL); 102 } else if (r == Bubbles.DISMISS_NO_LONGER_BUBBLE) { 103 log(b, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_NO_LONGER_BUBBLE); 104 } else if (r == Bubbles.DISMISS_BLOCKED) { 105 log(b, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BLOCKED); 106 } 107 } 108 109 /** 110 * @param b Bubble added to overflow 111 * @param r Reason that bubble was added to overflow 112 */ logOverflowAdd(Bubble b, @Bubbles.DismissReason int r)113 public void logOverflowAdd(Bubble b, @Bubbles.DismissReason int r) { 114 if (r == Bubbles.DISMISS_AGED) { 115 log(b, Event.BUBBLE_OVERFLOW_ADD_AGED); 116 } else if (r == Bubbles.DISMISS_USER_GESTURE) { 117 log(b, Event.BUBBLE_OVERFLOW_ADD_USER_GESTURE); 118 } else if (r == Bubbles.DISMISS_RELOAD_FROM_DISK) { 119 log(b, Event.BUBBLE_OVERFLOW_RECOVER); 120 } 121 } 122 logStackUiChanged(String packageName, int action, int bubbleCount, float normalX, float normalY)123 void logStackUiChanged(String packageName, int action, int bubbleCount, float normalX, 124 float normalY) { 125 FrameworkStatsLog.write(FrameworkStatsLog.BUBBLE_UI_CHANGED, 126 packageName, 127 null /* notification channel */, 128 0 /* notification ID */, 129 0 /* bubble position */, 130 bubbleCount, 131 action, 132 normalX, 133 normalY, 134 false /* unread bubble */, 135 false /* on-going bubble */, 136 false /* isAppForeground (unused) */); 137 } 138 logShowOverflow(String packageName, int currentUserId)139 void logShowOverflow(String packageName, int currentUserId) { 140 mUiEventLogger.log(BubbleLogger.Event.BUBBLE_OVERFLOW_SELECTED, currentUserId, 141 packageName); 142 } 143 logBubbleUiChanged(Bubble bubble, String packageName, int action, int bubbleCount, float normalX, float normalY, int index)144 void logBubbleUiChanged(Bubble bubble, String packageName, int action, int bubbleCount, 145 float normalX, float normalY, int index) { 146 FrameworkStatsLog.write(FrameworkStatsLog.BUBBLE_UI_CHANGED, 147 packageName, 148 bubble.getChannelId() /* notification channel */, 149 bubble.getNotificationId() /* notification ID */, 150 index, 151 bubbleCount, 152 action, 153 normalX, 154 normalY, 155 bubble.showInShade() /* isUnread */, 156 false /* isOngoing (unused) */, 157 false /* isAppForeground (unused) */); 158 } 159 }