Merge "[Notif] Blocking helper basic metrics" into pi-dev am: d53c5bb4f3
am: 67624094c9
Change-Id: Ic0a267fcc0289b41046c79349535278dfa72836b
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 42c774e..3efeb6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -76,6 +76,7 @@
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.HybridNotificationView;
+import com.android.systemui.statusbar.notification.NotificationCounters;
import com.android.systemui.statusbar.notification.NotificationInflater;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.NotificationViewWrapper;
@@ -1252,6 +1253,8 @@
Dependency.get(NotificationBlockingHelperManager.class);
boolean isBlockingHelperShown = manager.perhapsShowBlockingHelper(this, mMenuRow);
+ Dependency.get(MetricsLogger.class).count(NotificationCounters.NOTIFICATION_DISMISSED, 1);
+
// Continue with dismiss since we don't want the blocking helper to be directly associated
// with a certain notification.
performDismiss(fromAccessibility);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 65fb2da..a581049 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -30,6 +30,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -270,7 +271,8 @@
/** Animates out the guts view via either a fade or a circular reveal. */
- private void animateClose(int x, int y, boolean shouldDoCircularReveal) {
+ @VisibleForTesting
+ void animateClose(int x, int y, boolean shouldDoCircularReveal) {
if (shouldDoCircularReveal) {
// Circular reveal originating at (x, y)
if (x == -1 || y == -1) {
@@ -340,7 +342,8 @@
}
}
- private void setExposed(boolean exposed, boolean needsFalsingProtection) {
+ @VisibleForTesting
+ void setExposed(boolean exposed, boolean needsFalsingProtection) {
final boolean wasExposed = mExposed;
mExposed = exposed;
mNeedsFalsingProtection = needsFalsingProtection;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 6a1740c..ec49f43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -54,17 +54,20 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationCounters;
import java.util.List;
/**
- * The guts of a notification revealed when performing a long press.
+ * The guts of a notification revealed when performing a long press. This also houses the blocking
+ * helper affordance that allows a user to keep/stop notifications after swiping one away.
*/
public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
private static final String TAG = "InfoGuts";
private INotificationManager mINotificationManager;
private PackageManager mPm;
+ private MetricsLogger mMetricsLogger;
private String mPackageName;
private String mAppName;
@@ -84,17 +87,27 @@
private OnAppSettingsClickListener mAppSettingsClickListener;
private NotificationGuts mGutsContainer;
- /** Whether this view is being shown as part of the blocking helper */
+ /** Whether this view is being shown as part of the blocking helper. */
private boolean mIsForBlockingHelper;
private boolean mNegativeUserSentiment;
- private OnClickListener mOnKeepShowing = this::closeControls;
+ /** Counter tag that describes how the user exit or quit out of this view. */
+ private String mExitReasonCounter = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+ private OnClickListener mOnKeepShowing = v -> {
+ mExitReasonCounter = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
+ closeControls(v);
+ };
private OnClickListener mOnStopOrMinimizeNotifications = v -> {
+ mExitReasonCounter = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
swapContent(false);
};
private OnClickListener mOnUndo = v -> {
+ // Reset exit counter that we'll log and record an undo event separately (not an exit event)
+ mExitReasonCounter = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+ logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
swapContent(true);
};
@@ -151,6 +164,7 @@
boolean isUserSentimentNegative)
throws RemoteException {
mINotificationManager = iNotificationManager;
+ mMetricsLogger = Dependency.get(MetricsLogger.class);
mPackageName = pkg;
mNumUniqueChannelsInRow = numUniqueChannelsInRow;
mSbn = sbn;
@@ -183,6 +197,8 @@
bindHeader();
bindPrompt();
bindButtons();
+
+ logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_SHOWN);
}
private void bindHeader() throws RemoteException {
@@ -235,6 +251,8 @@
final int appUidF = mAppUid;
settingsButton.setOnClickListener(
(View view) -> {
+ logBlockingHelperCounter(
+ NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
mOnSettingsClickListener.onClick(view,
mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
appUidF);
@@ -269,6 +287,13 @@
}
}
+ @VisibleForTesting
+ void logBlockingHelperCounter(String counterTag) {
+ if (mIsForBlockingHelper) {
+ mMetricsLogger.count(counterTag, 1);
+ }
+ }
+
private boolean hasImportanceChanged() {
return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
}
@@ -437,25 +462,15 @@
*/
@VisibleForTesting
void closeControls(View v) {
- if (mIsForBlockingHelper) {
- NotificationBlockingHelperManager manager =
- Dependency.get(NotificationBlockingHelperManager.class);
- manager.dismissCurrentBlockingHelper();
-
- // Since this won't get a callback via gutsContainer.closeControls, save the new
- // importance values immediately.
- saveImportance();
- } else {
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
- }
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
}
@Override
@@ -480,6 +495,7 @@
if (save) {
saveImportance();
}
+ logBlockingHelperCounter(mExitReasonCounter);
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java
new file mode 100644
index 0000000..9a12e8b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCounters.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.systemui.statusbar.notification;
+
+/**
+ * Constants for counter tags for Notification-related actions/views.
+ */
+public class NotificationCounters {
+ /** Counter tag for notification dismissal. */
+ public static final String NOTIFICATION_DISMISSED = "notification_dismissed";
+
+ /** Counter tag for when the blocking helper is shown to the user. */
+ public static final String BLOCKING_HELPER_SHOWN = "blocking_helper_shown";
+ /** Counter tag for when the blocking helper is dismissed via a miscellaneous interaction. */
+ public static final String BLOCKING_HELPER_DISMISSED = "blocking_helper_dismissed";
+ /** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
+ public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
+ "blocking_helper_stop_notifications";
+ /** Counter tag for when the user hits 'keep showing' in the blocking helper. */
+ public static final String BLOCKING_HELPER_KEEP_SHOWING =
+ "blocking_helper_keep_showing";
+ /**
+ * Counter tag for when the user hits undo in context of the blocking helper - this can happen
+ * multiple times per view.
+ */
+ public static final String BLOCKING_HELPER_UNDO = "blocking_helper_undo";
+ /** Counter tag for when the user hits the notification settings icon in the blocking helper. */
+ public static final String BLOCKING_HELPER_NOTIF_SETTINGS =
+ "blocking_helper_notif_settings";
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index b0530c8..65fd7f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -33,9 +33,12 @@
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -44,7 +47,6 @@
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
-import android.app.NotificationManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -52,7 +54,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
-import android.os.Looper;
+import android.os.IBinder;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
@@ -65,6 +67,7 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -100,7 +103,7 @@
private StatusBarNotification mSbn;
@Rule public MockitoRule mockito = MockitoJUnit.rule();
- private Looper mLooper;
+ @Mock private MetricsLogger mMetricsLogger;
@Mock private INotificationManager mMockINotificationManager;
@Mock private PackageManager mMockPackageManager;
@Mock private NotificationBlockingHelperManager mBlockingHelperManager;
@@ -112,6 +115,7 @@
mBlockingHelperManager);
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+ mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
// Inflate the layout
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
@@ -301,6 +305,24 @@
}
@Test
+ public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
+ mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
+ verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+ }
+
+ @Test
+ public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
+ // Bind notification logs an event, so this counts as one invocation for the metrics logger.
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
+ true);
+ mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
+ verify(mMetricsLogger, times(2)).count(anyString(), anyInt());
+ }
+
+ @Test
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -471,6 +493,13 @@
false /* isNonblockable */, true /* isForBlockingHelper */,
true /* isUserSentimentNegative */);
+ NotificationGuts guts = spy(new NotificationGuts(mContext, null));
+ when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
+ doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
+ doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
+ guts.setGutsContent(mNotificationInfo);
+ mNotificationInfo.setGutsParent(guts);
+
mNotificationInfo.findViewById(R.id.keep).performClick();
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
@@ -495,6 +524,9 @@
false /* isNonblockable */,
true /* isForBlockingHelper */,
false /* isUserSentimentNegative */);
+ NotificationGuts guts = mock(NotificationGuts.class);
+ doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
+ mNotificationInfo.setGutsParent(guts);
mNotificationInfo.closeControls(mNotificationInfo);