Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79274542 authored by Rohan Shah's avatar Rohan Shah Committed by android-build-merger
Browse files

Merge "[Notif] Blocking helper basic metrics" into pi-dev am: d53c5bb4

am: 67624094

Change-Id: Ic0a267fcc0289b41046c79349535278dfa72836b
parents 492e53ee 67624094
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import com.android.systemui.statusbar.NotificationGuts.GutsContent;
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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
                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);
+5 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.view.ViewAnimationUtils;
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 @@ public class NotificationGuts extends FrameLayout {


    /** 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 @@ public class NotificationGuts extends FrameLayout {
        }
    }

    private void setExposed(boolean exposed, boolean needsFalsingProtection) {
    @VisibleForTesting
    void setExposed(boolean exposed, boolean needsFalsingProtection) {
        final boolean wasExposed = mExposed;
        mExposed = exposed;
        mNeedsFalsingProtection = needsFalsingProtection;
+38 −22
Original line number Diff line number Diff line
@@ -54,17 +54,20 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
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 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    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 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            boolean isUserSentimentNegative)
            throws RemoteException {
        mINotificationManager = iNotificationManager;
        mMetricsLogger = Dependency.get(MetricsLogger.class);
        mPackageName = pkg;
        mNumUniqueChannelsInRow = numUniqueChannelsInRow;
        mSbn = sbn;
@@ -183,6 +197,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        bindHeader();
        bindPrompt();
        bindButtons();

        logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_SHOWN);
    }

    private void bindHeader() throws RemoteException {
@@ -235,6 +251,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
            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 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        }
    }

    @VisibleForTesting
    void logBlockingHelperCounter(String counterTag) {
        if (mIsForBlockingHelper) {
            mMetricsLogger.count(counterTag, 1);
        }
    }

    private boolean hasImportanceChanged() {
        return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
    }
@@ -437,15 +462,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
     */
    @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);
@@ -456,7 +472,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        final int y = targetLoc[1] - parentLoc[1] + centerY;
        mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
    }
    }

    @Override
    public void setGutsParent(NotificationGuts guts) {
@@ -480,6 +495,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        if (save) {
            saveImportance();
        }
        logBlockingHelperCounter(mExitReasonCounter);
        return false;
    }

+44 −0
Original line number Diff line number Diff line
/*
 * 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";
}
+35 −3
Original line number Diff line number Diff line
@@ -33,9 +33,12 @@ import static org.mockito.Mockito.any;
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.INotificationManager;
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.PackageInfo;
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.view.View;
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 @@ public class NotificationInfoTest extends SysuiTestCase {
    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 @@ public class NotificationInfoTest extends SysuiTestCase {
                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,
@@ -300,6 +304,24 @@ public class NotificationInfoTest extends SysuiTestCase {
        assertEquals(View.VISIBLE, settingsButton.getVisibility());
    }

    @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);
@@ -471,6 +493,13 @@ public class NotificationInfoTest extends SysuiTestCase {
                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 @@ public class NotificationInfoTest extends SysuiTestCase {
                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);