Merge "add channel and group tags to the notificaiton logs" into oc-dev am: 76e76a5c26
am: 6b88afda65

Change-Id: I840c89e34b00cf505e50897bc7ba433f37a67dff
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 31b2dcc..d1ebc6e 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -318,6 +318,17 @@
     }
 
     /**
+     * The ID passed to setGroup(), or the override, or null.
+     * @hide
+     */
+    public String getGroup() {
+        if (overrideGroupKey != null) {
+            return overrideGroupKey;
+        }
+        return getNotification().getGroup();
+    }
+
+    /**
      * Sets the override group key.
      */
     public void setOverrideGroupKey(String overrideGroupKey) {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ddc9e6c..96f1d64 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3962,6 +3962,16 @@
     // OS: O
     APP_TRANSITION_BIND_APPLICATION_DELAY_MS = 945;
 
+    // FIELD - The group ID of a notification.
+    // Type: string
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_ID = 946;
+
+    // FIELD - If the notification is a group summary: 1.
+    // Type: int encoded boolean
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_SUMMARY = 947;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index feecb13..41682eb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2776,7 +2776,7 @@
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
+        n.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
         EventLogTags.writeNotificationAutogrouped(key);
     }
 
@@ -2785,7 +2785,7 @@
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(null);
+        n.setOverrideGroupKey(null);
         EventLogTags.writeNotificationUnautogrouped(key);
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 95e1db7..f3ae67e 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -73,6 +73,7 @@
 public final class NotificationRecord {
     static final String TAG = "NotificationRecord";
     static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int MAX_LOGTAG_LENGTH = 35;
     final StatusBarNotification sbn;
     final int mOriginalFlags;
     private final Context mContext;
@@ -127,6 +128,8 @@
     private boolean mShowBadge;
     private LogMaker mLogMaker;
     private Light mLight;
+    private String mGroupLogTag;
+    private String mChannelIdLogTag;
 
     @VisibleForTesting
     public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -749,6 +752,37 @@
         return sbn.getGroupKey();
     }
 
+    public void setOverrideGroupKey(String overrideGroupKey) {
+        sbn.setOverrideGroupKey(overrideGroupKey);
+        mGroupLogTag = null;
+    }
+
+    private String getGroupLogTag() {
+        if (mGroupLogTag == null) {
+            mGroupLogTag = shortenTag(sbn.getGroup());
+        }
+        return mGroupLogTag;
+    }
+
+    private String getChannelIdLogTag() {
+        if (mChannelIdLogTag == null) {
+            mChannelIdLogTag = shortenTag(mChannel.getId());
+        }
+        return mChannelIdLogTag;
+    }
+
+    private String shortenTag(String longTag) {
+        if (longTag == null) {
+            return null;
+        }
+        if (longTag.length() < MAX_LOGTAG_LENGTH) {
+            return longTag;
+        } else {
+            return longTag.substring(0, MAX_LOGTAG_LENGTH - 8) + "-" +
+                    Integer.toHexString(longTag.hashCode());
+        }
+    }
+
     public boolean isImportanceFromUser() {
         return mImportance == mUserImportance;
     }
@@ -806,16 +840,23 @@
 
     public LogMaker getLogMaker(long now) {
         if (mLogMaker == null) {
+            // initialize fields that only change on update (so a new record)
             mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
                     .setPackageName(sbn.getPackageName())
                     .addTaggedData(MetricsEvent.NOTIFICATION_ID, sbn.getId())
-                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
+                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.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()
                 .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
+                        sbn.getNotification().isGroupSummary() ? 1 : 0)
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 0812783..5a6225a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -35,6 +35,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.media.AudioAttributes;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -44,6 +45,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,6 +74,14 @@
     private final String channelId = "channel";
     NotificationChannel channel =
             new NotificationChannel(channelId, "test", NotificationManager.IMPORTANCE_DEFAULT);
+    private final String channelIdLong =
+            "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there";
+    final String groupId = "group";
+    final String groupIdOverride = "other_group";
+    private final String groupIdLong =
+            "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/";
+    NotificationChannel channelLongId =
+            new NotificationChannel(channelIdLong, "long", NotificationManager.IMPORTANCE_DEFAULT);
     NotificationChannel defaultChannel =
             new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
                     NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -107,7 +118,8 @@
     }
 
     private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
-            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
+            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights,
+            String group) {
         when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
         final Builder builder = new Builder(mMockContext)
                 .setContentTitle("foo")
@@ -151,6 +163,9 @@
             builder.setChannelId(channelId);
         }
 
+        if(group != null) {
+            builder.setGroup(group);
+        }
 
         Notification n = builder.build();
         if (preO) {
@@ -172,7 +187,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
@@ -185,7 +200,7 @@
         // pre upgrade, custom sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -199,7 +214,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -211,7 +226,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(null, record.getSound());
@@ -224,7 +239,7 @@
         // post upgrade, default sound.
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -237,7 +252,7 @@
         // pre upgrade, default vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNotNull(record.getVibration());
@@ -249,7 +264,7 @@
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_VIBRATION, record.getVibration());
@@ -262,7 +277,7 @@
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
@@ -274,7 +289,7 @@
         // post upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
@@ -284,7 +299,7 @@
     public void testImportance_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
     }
@@ -295,7 +310,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
@@ -307,7 +322,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
@@ -317,7 +332,7 @@
     public void testImportance_upgrade() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
     }
@@ -326,7 +341,7 @@
     public void testLights_preUpgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
@@ -336,7 +351,7 @@
     public void testLights_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_LIGHT, record.getLight());
     }
@@ -347,7 +362,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
@@ -366,7 +381,7 @@
                 defaultLightColor, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, true /*defaultLights */);
+                true /* lights */, true /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -382,7 +397,7 @@
                 Color.BLUE, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -391,8 +406,80 @@
     public void testLights_upgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
+
+    @Test
+    public void testLogmakerShortChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final LogMaker logMaker = record.getLogMaker();
+        assertEquals(channelId,
+                (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+    }
+
+    @Test
+    public void testLogmakerLongChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+        true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+        false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channelLongId);
+        final String loggedId = (String)
+            record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID);
+        assertEquals(channelIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerNoGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertNull(record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerShortGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*reO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerLongGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupIdLong /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final String loggedId = (String)
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID);
+        assertEquals(groupIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerOverrideGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(groupIdOverride);
+        assertEquals(groupIdOverride,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(null);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+
 }