Loading core/java/android/service/notification/StatusBarNotification.java +55 −0 Original line number Diff line number Diff line Loading @@ -22,16 +22,21 @@ import android.app.NotificationManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; /** * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including * the status bar and any {@link android.service.notification.NotificationListenerService}s. */ public class StatusBarNotification implements Parcelable { static final int MAX_LOG_TAG_LENGTH = 36; @UnsupportedAppUsage private final String pkg; @UnsupportedAppUsage Loading @@ -56,6 +61,9 @@ public class StatusBarNotification implements Parcelable { private Context mContext; // used for inflation & icon expansion // Contains the basic logging data of the notification. private LogMaker mLogMaker; /** @hide */ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, Notification notification, UserHandle user, Loading Loading @@ -381,4 +389,51 @@ public class StatusBarNotification implements Parcelable { } return mContext; } /** * Returns a LogMaker that contains all basic information of the notification. * @hide */ public LogMaker getLogMaker() { if (mLogMaker == null) { // Initialize fields that only change on update (so a new record). mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN) .setPackageName(getPackageName()) .addTaggedData(MetricsEvent.NOTIFICATION_ID, getId()) .addTaggedData(MetricsEvent.NOTIFICATION_TAG, getTag()) .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag()); } // Reset fields that can change between updates, or are used by multiple logs. return mLogMaker .clearCategory() .clearType() .clearSubtype() .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag()) .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY, getNotification().isGroupSummary() ? 1 : 0); } private String getGroupLogTag() { return shortenTag(getGroup()); } private String getChannelIdLogTag() { if (notification.getChannelId() == null) { return null; } return shortenTag(notification.getChannelId()); } // Make logTag with max size MAX_LOG_TAG_LENGTH. // For shorter or equal tags, returns the tag. // For longer tags, truncate the tag and append a hash of the full tag to // fill the maximum size. private String shortenTag(String logTag) { if (logTag == null || logTag.length() <= MAX_LOG_TAG_LENGTH) { return logTag; } String hash = Integer.toHexString(logTag.hashCode()); return logTag.substring(0, MAX_LOG_TAG_LENGTH - hash.length() - 1) + "-" + hash; } } core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java 0 → 100644 +152 −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 android.service.notification; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.Notification; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock private PackageManager mPm; private static final String PKG = "com.example.o"; private static final int UID = 9583; private static final int ID = 1; private static final String TAG = "tag1"; private static final String CHANNEL_ID = "channel"; private static final String CHANNEL_ID_LONG = "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there"; private static final String GROUP_ID_1 = "group1"; private static final String GROUP_ID_2 = "group2"; private static final String GROUP_ID_LONG = "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/"; private static final android.os.UserHandle USER = UserHandle.of(ActivityManager.getCurrentUser()); @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockContext.getResources()).thenReturn( InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); } @Test public void testLogMaker() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, CHANNEL_ID).getLogMaker(); assertEquals(CHANNEL_ID, (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID)); assertEquals(PKG, logMaker.getPackageName()); assertEquals(ID, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_ID)); assertEquals(TAG, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_TAG)); assertEquals(GROUP_ID_1, logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } @Test public void testLogMakerNoChannel() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, null).getLogMaker(); assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID)); } @Test public void testLogMakerLongChannel() { final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID_LONG).getLogMaker(); final String loggedId = (String) logMaker .getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID); assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length()); assertEquals(CHANNEL_ID_LONG.substring(0, 10), loggedId.substring(0, 10)); } @Test public void testLogMakerNoGroup() { final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID).getLogMaker(); assertNull( logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } @Test public void testLogMakerLongGroup() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_LONG, CHANNEL_ID) .getLogMaker(); final String loggedId = (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID); assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length()); assertEquals(GROUP_ID_LONG.substring(0, 10), loggedId.substring(0, 10)); } @Test public void testLogMakerOverrideGroup() { StatusBarNotification sbn = getNotification(PKG, GROUP_ID_1, CHANNEL_ID); assertEquals(GROUP_ID_1, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); sbn.setOverrideGroupKey(GROUP_ID_2); assertEquals(GROUP_ID_2, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); sbn.setOverrideGroupKey(null); assertEquals(GROUP_ID_1, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } private StatusBarNotification getNotification(String pkg, String group, String channelId) { final Notification.Builder builder = new Notification.Builder(mMockContext, channelId) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon); if (group != null) { builder.setGroup(group); } Notification n = builder.build(); return new StatusBarNotification( pkg, pkg, ID, TAG, UID, UID, n, USER, null, UID); } } packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ import static android.service.notification.NotificationListenerService.Ranking .USER_SENTIMENT_NEGATIVE; import android.content.Context; import android.metrics.LogMaker; import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.NotificationEntryManager; Loading Loading @@ -58,6 +60,8 @@ public class NotificationBlockingHelperManager { */ private boolean mIsShadeExpanded; private MetricsLogger mMetricsLogger = new MetricsLogger(); @Inject public NotificationBlockingHelperManager(Context context) { mContext = context; Loading Loading @@ -100,6 +104,11 @@ public class NotificationBlockingHelperManager { mBlockingHelperRow = row; mBlockingHelperRow.setBlockingHelperShowing(true); // Log triggering of blocking helper by the system. This log line // should be emitted before the "display" log line. mMetricsLogger.write( getLogMaker().setSubtype(MetricsEvent.BLOCKING_HELPER_TRIGGERED_BY_SYSTEM)); // We don't care about the touch origin (x, y) since we're opening guts without any // explicit user interaction. manager.openGuts(mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext)); Loading Loading @@ -153,6 +162,13 @@ public class NotificationBlockingHelperManager { || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName)); } private LogMaker getLogMaker() { return mBlockingHelperRow.getStatusBarNotification() .getLogMaker() .setCategory(MetricsEvent.NOTIFICATION_ITEM) .setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER); } // Format must stay in sync with frameworks/base/core/res/res/values/config.xml // config_nonBlockableNotificationPackages private String makeChannelKey(String pkg, String channel) { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -123,11 +123,15 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private OnClickListener mOnKeepShowing = v -> { mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING; closeControls(v); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT)); }; private OnClickListener mOnToggleSilent = v -> { Runnable saveImportance = () -> { swapContent(ACTION_TOGGLE_SILENT, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME)); }; if (mCheckSaveListener != null) { mCheckSaveListener.checkSave(saveImportance, mSbn); Loading @@ -139,6 +143,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private OnClickListener mOnStopOrMinimizeNotifications = v -> { Runnable saveImportance = () -> { swapContent(ACTION_BLOCK, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED)); }; if (mCheckSaveListener != null) { mCheckSaveListener.checkSave(saveImportance, mSbn); Loading @@ -153,6 +159,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO); mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS)); swapContent(ACTION_UNDO, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO)); }; public NotificationInfo(Context context, AttributeSet attrs) { Loading Loading @@ -251,6 +259,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G bindHeader(); bindPrompt(); bindButtons(); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_DISPLAY)); } private void bindHeader() throws RemoteException { Loading Loading @@ -588,6 +599,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G confirmation.setAlpha(1f); header.setVisibility(VISIBLE); header.setAlpha(1f); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_DISMISS)); } @Override Loading Loading @@ -733,4 +746,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } } } private LogMaker getLogMaker() { return mSbn.getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM); } } packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ 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.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.app.INotificationManager; Loading Loading @@ -73,6 +72,7 @@ import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; Loading Loading @@ -498,12 +498,15 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception { public void testLogBlockingHelperCounter_logGutsViewDisplayed() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false, IMPORTANCE_DEFAULT); mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent"); verifyZeroInteractions(mMetricsLogger); verify(mMetricsLogger).write(argThat(logMaker -> logMaker.getType() == MetricsEvent.NOTIFICATION_BLOCKING_HELPER && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_DISPLAY )); } @Test Loading Loading
core/java/android/service/notification/StatusBarNotification.java +55 −0 Original line number Diff line number Diff line Loading @@ -22,16 +22,21 @@ import android.app.NotificationManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; /** * Class encapsulating a Notification. Sent by the NotificationManagerService to clients including * the status bar and any {@link android.service.notification.NotificationListenerService}s. */ public class StatusBarNotification implements Parcelable { static final int MAX_LOG_TAG_LENGTH = 36; @UnsupportedAppUsage private final String pkg; @UnsupportedAppUsage Loading @@ -56,6 +61,9 @@ public class StatusBarNotification implements Parcelable { private Context mContext; // used for inflation & icon expansion // Contains the basic logging data of the notification. private LogMaker mLogMaker; /** @hide */ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, Notification notification, UserHandle user, Loading Loading @@ -381,4 +389,51 @@ public class StatusBarNotification implements Parcelable { } return mContext; } /** * Returns a LogMaker that contains all basic information of the notification. * @hide */ public LogMaker getLogMaker() { if (mLogMaker == null) { // Initialize fields that only change on update (so a new record). mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN) .setPackageName(getPackageName()) .addTaggedData(MetricsEvent.NOTIFICATION_ID, getId()) .addTaggedData(MetricsEvent.NOTIFICATION_TAG, getTag()) .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag()); } // Reset fields that can change between updates, or are used by multiple logs. return mLogMaker .clearCategory() .clearType() .clearSubtype() .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag()) .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY, getNotification().isGroupSummary() ? 1 : 0); } private String getGroupLogTag() { return shortenTag(getGroup()); } private String getChannelIdLogTag() { if (notification.getChannelId() == null) { return null; } return shortenTag(notification.getChannelId()); } // Make logTag with max size MAX_LOG_TAG_LENGTH. // For shorter or equal tags, returns the tag. // For longer tags, truncate the tag and append a hash of the full tag to // fill the maximum size. private String shortenTag(String logTag) { if (logTag == null || logTag.length() <= MAX_LOG_TAG_LENGTH) { return logTag; } String hash = Integer.toHexString(logTag.hashCode()); return logTag.substring(0, MAX_LOG_TAG_LENGTH - hash.length() - 1) + "-" + hash; } }
core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java 0 → 100644 +152 −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 android.service.notification; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.Notification; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.metrics.LogMaker; import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock private PackageManager mPm; private static final String PKG = "com.example.o"; private static final int UID = 9583; private static final int ID = 1; private static final String TAG = "tag1"; private static final String CHANNEL_ID = "channel"; private static final String CHANNEL_ID_LONG = "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there"; private static final String GROUP_ID_1 = "group1"; private static final String GROUP_ID_2 = "group2"; private static final String GROUP_ID_LONG = "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/"; private static final android.os.UserHandle USER = UserHandle.of(ActivityManager.getCurrentUser()); @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockContext.getResources()).thenReturn( InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); } @Test public void testLogMaker() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, CHANNEL_ID).getLogMaker(); assertEquals(CHANNEL_ID, (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID)); assertEquals(PKG, logMaker.getPackageName()); assertEquals(ID, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_ID)); assertEquals(TAG, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_TAG)); assertEquals(GROUP_ID_1, logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } @Test public void testLogMakerNoChannel() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, null).getLogMaker(); assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID)); } @Test public void testLogMakerLongChannel() { final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID_LONG).getLogMaker(); final String loggedId = (String) logMaker .getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID); assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length()); assertEquals(CHANNEL_ID_LONG.substring(0, 10), loggedId.substring(0, 10)); } @Test public void testLogMakerNoGroup() { final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID).getLogMaker(); assertNull( logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } @Test public void testLogMakerLongGroup() { final LogMaker logMaker = getNotification(PKG, GROUP_ID_LONG, CHANNEL_ID) .getLogMaker(); final String loggedId = (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID); assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length()); assertEquals(GROUP_ID_LONG.substring(0, 10), loggedId.substring(0, 10)); } @Test public void testLogMakerOverrideGroup() { StatusBarNotification sbn = getNotification(PKG, GROUP_ID_1, CHANNEL_ID); assertEquals(GROUP_ID_1, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); sbn.setOverrideGroupKey(GROUP_ID_2); assertEquals(GROUP_ID_2, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); sbn.setOverrideGroupKey(null); assertEquals(GROUP_ID_1, sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID)); } private StatusBarNotification getNotification(String pkg, String group, String channelId) { final Notification.Builder builder = new Notification.Builder(mMockContext, channelId) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon); if (group != null) { builder.setGroup(group); } Notification n = builder.build(); return new StatusBarNotification( pkg, pkg, ID, TAG, UID, UID, n, USER, null, UID); } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -20,11 +20,13 @@ import static android.service.notification.NotificationListenerService.Ranking .USER_SENTIMENT_NEGATIVE; import android.content.Context; import android.metrics.LogMaker; import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.NotificationEntryManager; Loading Loading @@ -58,6 +60,8 @@ public class NotificationBlockingHelperManager { */ private boolean mIsShadeExpanded; private MetricsLogger mMetricsLogger = new MetricsLogger(); @Inject public NotificationBlockingHelperManager(Context context) { mContext = context; Loading Loading @@ -100,6 +104,11 @@ public class NotificationBlockingHelperManager { mBlockingHelperRow = row; mBlockingHelperRow.setBlockingHelperShowing(true); // Log triggering of blocking helper by the system. This log line // should be emitted before the "display" log line. mMetricsLogger.write( getLogMaker().setSubtype(MetricsEvent.BLOCKING_HELPER_TRIGGERED_BY_SYSTEM)); // We don't care about the touch origin (x, y) since we're opening guts without any // explicit user interaction. manager.openGuts(mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext)); Loading Loading @@ -153,6 +162,13 @@ public class NotificationBlockingHelperManager { || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName)); } private LogMaker getLogMaker() { return mBlockingHelperRow.getStatusBarNotification() .getLogMaker() .setCategory(MetricsEvent.NOTIFICATION_ITEM) .setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER); } // Format must stay in sync with frameworks/base/core/res/res/values/config.xml // config_nonBlockableNotificationPackages private String makeChannelKey(String pkg, String channel) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -123,11 +123,15 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private OnClickListener mOnKeepShowing = v -> { mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING; closeControls(v); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT)); }; private OnClickListener mOnToggleSilent = v -> { Runnable saveImportance = () -> { swapContent(ACTION_TOGGLE_SILENT, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_ALERT_ME)); }; if (mCheckSaveListener != null) { mCheckSaveListener.checkSave(saveImportance, mSbn); Loading @@ -139,6 +143,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private OnClickListener mOnStopOrMinimizeNotifications = v -> { Runnable saveImportance = () -> { swapContent(ACTION_BLOCK, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED)); }; if (mCheckSaveListener != null) { mCheckSaveListener.checkSave(saveImportance, mSbn); Loading @@ -153,6 +159,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO); mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS)); swapContent(ACTION_UNDO, true /* animate */); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO)); }; public NotificationInfo(Context context, AttributeSet attrs) { Loading Loading @@ -251,6 +259,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G bindHeader(); bindPrompt(); bindButtons(); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_DISPLAY)); } private void bindHeader() throws RemoteException { Loading Loading @@ -588,6 +599,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G confirmation.setAlpha(1f); header.setVisibility(VISIBLE); header.setAlpha(1f); mMetricsLogger.write(getLogMaker().setType(MetricsEvent.NOTIFICATION_BLOCKING_HELPER) .setSubtype(MetricsEvent.BLOCKING_HELPER_DISMISS)); } @Override Loading Loading @@ -733,4 +746,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } } } private LogMaker getLogMaker() { return mSbn.getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM); } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +6 −3 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ 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.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.app.INotificationManager; Loading Loading @@ -73,6 +72,7 @@ import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; Loading Loading @@ -498,12 +498,15 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception { public void testLogBlockingHelperCounter_logGutsViewDisplayed() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false, IMPORTANCE_DEFAULT); mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent"); verifyZeroInteractions(mMetricsLogger); verify(mMetricsLogger).write(argThat(logMaker -> logMaker.getType() == MetricsEvent.NOTIFICATION_BLOCKING_HELPER && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_DISPLAY )); } @Test Loading