diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index 5c802bd2e5b79..df1de63b65a01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -24,6 +24,7 @@ import android.os.Handler; import android.view.accessibility.AccessibilityManager; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.dagger.qualifiers.Background; @@ -116,7 +117,8 @@ public interface NotificationsModule { ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, Provider builderProvider, - BubbleController bubbleController) { + BubbleController bubbleController, + UiEventLogger uiEventLogger) { return new NotificationGutsManager( context, visualStabilityManager, @@ -131,7 +133,8 @@ public interface NotificationsModule { channelEditorDialogController, contextTracker, builderProvider, - bubbleController); + bubbleController, + uiEventLogger); } /** Provides an instance of {@link VisualStabilityManager} */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java index e445c9d73bbbe..28c53dc6d9b26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java @@ -31,6 +31,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; @@ -50,6 +51,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon private MetricsLogger mMetricsLogger; private OnSettingsClickListener mOnSettingsClickListener; private NotificationGuts mGutsContainer; + private UiEventLogger mUiEventLogger; private OnClickListener mOnOk = v -> { mGutsContainer.closeControls(v, false); @@ -66,6 +68,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon public void bindGuts(final PackageManager pm, final OnSettingsClickListener onSettingsClick, final StatusBarNotification sbn, + final UiEventLogger uiEventLogger, ArraySet activeOps) { mPkg = sbn.getPackageName(); mSbn = sbn; @@ -73,11 +76,13 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon mAppName = mPkg; mOnSettingsClickListener = onSettingsClick; mAppOps = activeOps; + mUiEventLogger = uiEventLogger; bindHeader(); bindPrompt(); bindButtons(); + logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN); mMetricsLogger = new MetricsLogger(); mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true); } @@ -188,6 +193,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon @Override public boolean handleCloseControls(boolean save, boolean force) { + logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_CLOSE); if (mMetricsLogger != null) { mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false); } @@ -198,4 +204,11 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon public int getActualHeight() { return getHeight(); } + + private void logUiEvent(NotificationAppOpsEvent event) { + if (mSbn != null) { + mUiEventLogger.logWithInstanceId(event, + mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId()); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java new file mode 100644 index 0000000000000..c856245ebe833 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationAppOpsEvent.java @@ -0,0 +1,41 @@ +/* + * 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.systemui.statusbar.notification.row; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; + +enum NotificationAppOpsEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "User opened app ops controls on a notification (for active " + + "privacy-sensitive permissions usage)") + NOTIFICATION_APP_OPS_OPEN(597), + + @UiEvent(doc = "User closed app ops controls") + NOTIFICATION_APP_OPS_CLOSE(598), + + @UiEvent(doc = "User clicked through to settings in app ops controls") + NOTIFICATION_APP_OPS_SETTINGS_CLICK(599); + + private final int mId; + NotificationAppOpsEvent(int id) { + mId = id; + } + @Override public int getId() { + return mId; + } +} + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java new file mode 100644 index 0000000000000..6833326d47e59 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationControlsEvent.java @@ -0,0 +1,40 @@ +/* + * 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.systemui.statusbar.notification.row; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; + +enum NotificationControlsEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "The user opened the notification inline controls.") + NOTIFICATION_CONTROLS_OPEN(594), + + @UiEvent(doc = "In notification inline controls, the user saved a notification channel " + + "importance change.") + NOTIFICATION_CONTROLS_SAVE_IMPORTANCE(595), + + @UiEvent(doc = "The user closed the notification inline controls.") + NOTIFICATION_CONTROLS_CLOSE(596); + + private final int mId; + NotificationControlsEvent(int id) { + mId = id; + } + @Override public int getId() { + return mId; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 8337cbe449d5a..24883f51a984d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -41,6 +41,7 @@ import android.view.accessibility.AccessibilityManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.settingslib.notification.ConversationIconFactory; import com.android.systemui.Dependency; @@ -121,6 +122,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx private final ShortcutManager mShortcutManager; private final CurrentUserContextTracker mContextTracker; private final Provider mBuilderProvider; + private final UiEventLogger mUiEventLogger; /** * Injected constructor. See {@link NotificationsModule}. @@ -135,7 +137,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx ChannelEditorDialogController channelEditorDialogController, CurrentUserContextTracker contextTracker, Provider builderProvider, - BubbleController bubbleController) { + BubbleController bubbleController, + UiEventLogger uiEventLogger) { mContext = context; mVisualStabilityManager = visualStabilityManager; mStatusBarLazy = statusBarLazy; @@ -150,6 +153,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mBuilderProvider = builderProvider; mChannelEditorDialogController = channelEditorDialogController; mBubbleController = bubbleController; + mUiEventLogger = uiEventLogger; } public void setUpWithPresenter(NotificationPresenter presenter, @@ -315,12 +319,16 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx AppOpsInfo.OnSettingsClickListener onSettingsClick = (View v, String pkg, int uid, ArraySet ops) -> { - mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS); - guts.resetFalsingCheck(); - startAppOpsSettingsActivity(pkg, uid, ops, row); + mUiEventLogger.logWithInstanceId( + NotificationAppOpsEvent.NOTIFICATION_APP_OPS_SETTINGS_CLICK, + sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId()); + mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS); + guts.resetFalsingCheck(); + startAppOpsSettingsActivity(pkg, uid, ops, row); }; if (!row.getEntry().mActiveAppOps.isEmpty()) { - appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, row.getEntry().mActiveAppOps); + appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, mUiEventLogger, + row.getEntry().mActiveAppOps); } } @@ -370,6 +378,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx row.getEntry(), onSettingsClick, onAppSettingsClick, + mUiEventLogger, mDeviceProvisionedController.isDeviceProvisioned(), row.getIsNonblockable(), mHighPriorityProvider.isHighPriority(row.getEntry())); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java index a131ebef77dbb..f0c93b10578cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java @@ -56,6 +56,7 @@ import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -122,6 +123,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private OnAppSettingsClickListener mAppSettingsClickListener; private NotificationGuts mGutsContainer; private Drawable mPkgIcon; + private UiEventLogger mUiEventLogger; @VisibleForTesting boolean mSkipPost = false; @@ -182,6 +184,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G NotificationEntry entry, OnSettingsClickListener onSettingsClick, OnAppSettingsClickListener onAppSettingsClick, + UiEventLogger uiEventLogger, boolean isDeviceProvisioned, boolean isNonblockable, boolean wasShownHighPriority) @@ -205,6 +208,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G mAppUid = mSbn.getUid(); mDelegatePkg = mSbn.getOpPkg(); mIsDeviceProvisioned = isDeviceProvisioned; + mUiEventLogger = uiEventLogger; int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage( pkg, mAppUid, false /* includeDeleted */); @@ -223,6 +227,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G bindInlineControls(); + logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN); mMetricsLogger.write(notificationControlsLogMaker()); } @@ -397,6 +402,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G */ private void updateImportance() { if (mChosenImportance != null) { + logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE); mMetricsLogger.write(importanceChangeLogMaker()); int newImportance = mChosenImportance; @@ -483,6 +489,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G bindInlineControls(); + logUiEvent(NotificationControlsEvent.NOTIFICATION_CONTROLS_CLOSE); mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE)); } @@ -627,6 +634,13 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } } + private void logUiEvent(NotificationControlsEvent event) { + if (mSbn != null) { + mUiEventLogger.logWithInstanceId(event, + mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId()); + } + } + /** * Returns a LogMaker with all available notification information. * Caller should set category, type, and maybe subtype, before passing it to mMetricsLogger. diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java index ec73a75719698..43d8b50bcf72e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java @@ -49,6 +49,7 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -69,6 +70,7 @@ public class AppOpsInfoTest extends SysuiTestCase { private final PackageManager mMockPackageManager = mock(PackageManager.class); private final NotificationGuts mGutsParent = mock(NotificationGuts.class); private StatusBarNotification mSbn; + private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake(); @Before public void setUp() throws Exception { @@ -94,7 +96,7 @@ public class AppOpsInfoTest extends SysuiTestCase { @Test public void testBindNotification_SetsTextApplicationName() { when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>()); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname); assertTrue(textView.getText().toString().contains("App Name")); } @@ -104,7 +106,7 @@ public class AppOpsInfoTest extends SysuiTestCase { final Drawable iconDrawable = mock(Drawable.class); when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) .thenReturn(iconDrawable); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, new ArraySet<>()); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon); assertEquals(iconDrawable, iconView.getDrawable()); } @@ -120,7 +122,7 @@ public class AppOpsInfoTest extends SysuiTestCase { assertEquals(expectedOps, ops); assertEquals(TEST_UID, uid); latch.countDown(); - }, mSbn, expectedOps); + }, mSbn, mUiEventLogger, expectedOps); final View settingsButton = mAppOpsInfo.findViewById(R.id.settings); settingsButton.performClick(); @@ -128,6 +130,14 @@ public class AppOpsInfoTest extends SysuiTestCase { assertEquals(0, latch.getCount()); } + @Test + public void testBindNotification_LogsOpen() throws Exception { + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); + assertEquals(1, mUiEventLogger.numLogs()); + assertEquals(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN.getId(), + mUiEventLogger.eventId(0)); + } + @Test public void testOk() { ArraySet expectedOps = new ArraySet<>(); @@ -139,7 +149,7 @@ public class AppOpsInfoTest extends SysuiTestCase { assertEquals(expectedOps, ops); assertEquals(TEST_UID, uid); latch.countDown(); - }, mSbn, expectedOps); + }, mSbn, mUiEventLogger, expectedOps); final View okButton = mAppOpsInfo.findViewById(R.id.ok); okButton.performClick(); @@ -151,7 +161,7 @@ public class AppOpsInfoTest extends SysuiTestCase { public void testPrompt_camera() { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_CAMERA); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is using the camera.", prompt.getText()); } @@ -160,7 +170,7 @@ public class AppOpsInfoTest extends SysuiTestCase { public void testPrompt_mic() { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_RECORD_AUDIO); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is using the microphone.", prompt.getText()); } @@ -169,7 +179,7 @@ public class AppOpsInfoTest extends SysuiTestCase { public void testPrompt_overlay() { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is displaying over other apps on your screen.", prompt.getText()); } @@ -179,7 +189,7 @@ public class AppOpsInfoTest extends SysuiTestCase { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_CAMERA); expectedOps.add(OP_RECORD_AUDIO); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is using the microphone and camera.", prompt.getText()); } @@ -190,7 +200,7 @@ public class AppOpsInfoTest extends SysuiTestCase { expectedOps.add(OP_CAMERA); expectedOps.add(OP_RECORD_AUDIO); expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is displaying over other apps on your screen and using" + " the microphone and camera.", prompt.getText()); @@ -201,7 +211,7 @@ public class AppOpsInfoTest extends SysuiTestCase { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_CAMERA); expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is displaying over other apps on your screen and using" + " the camera.", prompt.getText()); @@ -212,7 +222,7 @@ public class AppOpsInfoTest extends SysuiTestCase { ArraySet expectedOps = new ArraySet<>(); expectedOps.add(OP_RECORD_AUDIO); expectedOps.add(OP_SYSTEM_ALERT_WINDOW); - mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, expectedOps); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); assertEquals("This app is displaying over other apps on your screen and using" + " the microphone.", prompt.getText()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 5b5873b7a1cfe..9dee84347ae1f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -64,6 +64,8 @@ import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; @@ -149,7 +151,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase { mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager, () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider, mINotificationManager, mLauncherApps, mShortcutManager, - mChannelEditorDialogController, mContextTracker, mProvider, mBubbleController); + mChannelEditorDialogController, mContextTracker, mProvider, mBubbleController, + new UiEventLoggerFake()); mGutsManager.setUpWithPresenter(mPresenter, mStackScroller, mCheckSaveListener, mOnSettingsClickListener); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); @@ -362,6 +365,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(entry), any(NotificationInfo.OnSettingsClickListener.class), any(NotificationInfo.OnAppSettingsClickListener.class), + any(UiEventLogger.class), eq(false), eq(false), eq(true) /* wasShownHighPriority */); @@ -394,6 +398,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(entry), any(NotificationInfo.OnSettingsClickListener.class), any(NotificationInfo.OnAppSettingsClickListener.class), + any(UiEventLogger.class), eq(true), eq(false), eq(false) /* wasShownHighPriority */); @@ -424,6 +429,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(entry), any(NotificationInfo.OnSettingsClickListener.class), any(NotificationInfo.OnAppSettingsClickListener.class), + any(UiEventLogger.class), eq(false), eq(false), eq(false) /* wasShownHighPriority */); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java index 6bf60721cd8ed..ed982ab7d989a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java @@ -62,6 +62,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -102,6 +103,7 @@ public class NotificationInfoTest extends SysuiTestCase { private Set mDefaultNotificationChannelSet = new HashSet<>(); private StatusBarNotification mSbn; private NotificationEntry mEntry; + private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake(); @Rule public MockitoRule mockito = MockitoJUnit.rule(); @@ -187,6 +189,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -211,6 +214,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -231,6 +235,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -260,6 +265,7 @@ public class NotificationInfoTest extends SysuiTestCase { entry, null, null, + mUiEventLogger, true, false, true); @@ -281,6 +287,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -307,6 +314,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -328,6 +336,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -348,6 +357,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -372,6 +382,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -392,6 +403,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, true, true); @@ -416,6 +428,7 @@ public class NotificationInfoTest extends SysuiTestCase { latch.countDown(); }, null, + mUiEventLogger, true, false, true); @@ -439,6 +452,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -462,6 +476,7 @@ public class NotificationInfoTest extends SysuiTestCase { assertEquals(mNotificationChannel, c); }, null, + mUiEventLogger, false, false, true); @@ -482,6 +497,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -496,6 +512,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, (View v, NotificationChannel c, int appUid) -> { }, null, + mUiEventLogger, true, false, true); @@ -519,6 +536,7 @@ public class NotificationInfoTest extends SysuiTestCase { latch.countDown(); }, null, + mUiEventLogger, true, true, true); @@ -543,6 +561,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -565,6 +584,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -587,6 +607,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, true, true); @@ -611,6 +632,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -630,6 +652,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -649,6 +672,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -657,6 +681,28 @@ public class NotificationInfoTest extends SysuiTestCase { anyString(), eq(TEST_UID), any()); } + @Test + public void testBindNotification_LogsOpen() throws Exception { + mNotificationInfo.bindNotification( + mMockPackageManager, + mMockINotificationManager, + mVisualStabilityManager, + mChannelEditorDialogController, + TEST_PACKAGE_NAME, + mNotificationChannel, + mNotificationChannelSet, + mEntry, + null, + null, + mUiEventLogger, + true, + false, + true); + assertEquals(1, mUiEventLogger.numLogs()); + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(), + mUiEventLogger.eventId(0)); + } + @Test public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception { mNotificationChannel.setImportance(IMPORTANCE_LOW); @@ -671,6 +717,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -696,6 +743,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -721,6 +769,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -730,6 +779,13 @@ public class NotificationInfoTest extends SysuiTestCase { verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( anyString(), eq(TEST_UID), any()); assertEquals(originalImportance, mNotificationChannel.getImportance()); + + assertEquals(2, mUiEventLogger.numLogs()); + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(), + mUiEventLogger.eventId(0)); + // The SAVE_IMPORTANCE event is logged whenever importance is saved, even if unchanged. + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE.getId(), + mUiEventLogger.eventId(1)); } @Test @@ -747,6 +803,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -773,6 +830,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -789,6 +847,12 @@ public class NotificationInfoTest extends SysuiTestCase { assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance()); + + assertEquals(2, mUiEventLogger.numLogs()); + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(), + mUiEventLogger.eventId(0)); + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_SAVE_IMPORTANCE.getId(), + mUiEventLogger.eventId(1)); } @Test @@ -805,6 +869,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -838,6 +903,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -871,6 +937,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -907,6 +974,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -942,6 +1010,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, true); @@ -968,6 +1037,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -997,6 +1067,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -1029,6 +1100,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false); @@ -1040,6 +1112,10 @@ public class NotificationInfoTest extends SysuiTestCase { mTestableLooper.processAllMessages(); verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel)); + + assertEquals(1, mUiEventLogger.numLogs()); + assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(), + mUiEventLogger.eventId(0)); } @Test @@ -1056,6 +1132,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false @@ -1088,6 +1165,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false @@ -1113,6 +1191,7 @@ public class NotificationInfoTest extends SysuiTestCase { mEntry, null, null, + mUiEventLogger, true, false, false