Merge "NotificationReported atom: Hash free-string ids."

This commit is contained in:
TreeHugger Robot
2020-02-12 03:06:07 +00:00
committed by Android (Google) Code Review
4 changed files with 188 additions and 37 deletions

View File

@@ -3475,27 +3475,25 @@ message NotificationReported {
// A small system-assigned identifier for the notification.
// Locally probably-unique, but expect collisions across users and/or days.
optional int32 instance_id = 4;
// The app-assigned notification ID and tag
optional int32 notification_id = 5;
optional string notification_tag = 6;
optional string channel_id = 7; // App-assigned channel ID
optional int32 notification_id_hash = 5; // Small hash of the app-assigned notif ID + tag
optional int32 channel_id_hash = 6; // Small hash of app-assigned channel ID
// Grouping information
optional string group_id = 8; // Group the notification currently belongs to
optional int32 group_instance_id = 9; // Instance_id of the group-summary notification
optional bool is_group_summary = 10; // Tags the group-summary notification
optional int32 group_id_hash = 7; // Small hash of the group ID of the notification
optional int32 group_instance_id = 8; // Instance_id of the group-summary notification
optional bool is_group_summary = 9; // Tags the group-summary notification
// Attributes
optional string category = 11; // App-assigned notification category (API-defined strings)
optional int32 style = 12; // App-assigned notification style
optional int32 num_people = 13; // Number of Person records attached to the notification
optional string category = 10; // App-assigned notification category (API-defined strings)
optional int32 style = 11; // App-assigned notification style
optional int32 num_people = 12; // Number of Person records attached to the notification
// Ordering, importance and interruptiveness
optional int32 position = 14; // Position in NotificationManager's list
optional int32 position = 13; // Position in NotificationManager's list
optional android.stats.sysui.NotificationImportance importance = 15;
optional int32 alerting = 16; // Bitfield, 1=buzz 2=beep 4=blink
optional android.stats.sysui.NotificationImportance importance = 14;
optional int32 alerting = 15; // Bitfield, 1=buzz 2=beep 4=blink
enum NotificationImportanceExplanation {
IMPORTANCE_EXPLANATION_UNKNOWN = 0;
@@ -3507,12 +3505,12 @@ message NotificationReported {
IMPORTANCE_EXPLANATION_APP_PRE_CHANNELS = 5;
}
optional NotificationImportanceExplanation importance_source = 17;
optional android.stats.sysui.NotificationImportance importance_initial = 18;
optional NotificationImportanceExplanation importance_initial_source = 19;
optional android.stats.sysui.NotificationImportance importance_asst = 20;
optional int32 assistant_hash = 21;
optional float assistant_ranking_score = 22;
optional NotificationImportanceExplanation importance_source = 16;
optional android.stats.sysui.NotificationImportance importance_initial = 17;
optional NotificationImportanceExplanation importance_initial_source = 18;
optional android.stats.sysui.NotificationImportance importance_asst = 19;
optional int32 assistant_hash = 20;
optional float assistant_ranking_score = 21;
}
message Notification {

View File

@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -266,5 +267,39 @@ public interface NotificationRecordLogger {
int getInstanceId() {
return (r.getSbn().getInstanceId() == null ? 0 : r.getSbn().getInstanceId().getId());
}
/**
* @return Small hash of the notification ID, and tag (if present).
*/
int getNotificationIdHash() {
return smallHash(Objects.hashCode(r.getSbn().getTag()) ^ r.getSbn().getId());
}
/**
* @return Small hash of the channel ID, if present, or 0 otherwise.
*/
int getChannelIdHash() {
return smallHash(Objects.hashCode(r.getSbn().getNotification().getChannelId()));
}
/**
* @return Small hash of the group ID, respecting group override if present. 0 otherwise.
*/
int getGroupIdHash() {
return smallHash(Objects.hashCode(r.getSbn().getGroup()));
}
// "Small" hashes will be in the range [0, MAX_HASH).
static final int MAX_HASH = (1 << 13);
/**
* Maps in to the range [0, MAX_HASH), keeping similar values distinct.
* @param in An arbitrary integer.
* @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH).
*/
@VisibleForTesting
static int smallHash(int in) {
return Math.floorMod(in, MAX_HASH);
}
}
}

View File

@@ -40,28 +40,27 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
/* int32 uid = 2 */ r.getUid(),
/* string package_name = 3 */ r.getSbn().getPackageName(),
/* int32 instance_id = 4 */ p.getInstanceId(),
/* int32 notification_id = 5 */ r.getSbn().getId(),
/* string notification_tag = 6 */ r.getSbn().getTag(),
/* string channel_id = 7 */ r.getSbn().getChannelIdLogTag(),
/* string group_id = 8 */ r.getSbn().getGroupLogTag(),
/* int32 group_instance_id = 9 */ 0, // TODO generate and fill instance ids
/* bool is_group_summary = 10 */ r.getSbn().getNotification().isGroupSummary(),
/* string category = 11 */ r.getSbn().getNotification().category,
/* int32 style = 12 */ p.getStyle(),
/* int32 num_people = 13 */ p.getNumPeople(),
/* int32 position = 14 */ position,
/* android.stats.sysui.NotificationImportance importance = 15 */ r.getImportance(),
/* int32 alerting = 16 */ buzzBeepBlink,
/* NotificationImportanceExplanation importance_source = 17 */
/* int32 notification_id_hash = 5 */ p.getNotificationIdHash(),
/* int32 channel_id_hash = 6 */ p.getChannelIdHash(),
/* string group_id_hash = 7 */ p.getGroupIdHash(),
/* int32 group_instance_id = 8 */ 0, // TODO generate and fill instance ids
/* bool is_group_summary = 9 */ r.getSbn().getNotification().isGroupSummary(),
/* string category = 10 */ r.getSbn().getNotification().category,
/* int32 style = 11 */ p.getStyle(),
/* int32 num_people = 12 */ p.getNumPeople(),
/* int32 position = 13 */ position,
/* android.stats.sysui.NotificationImportance importance = 14 */ r.getImportance(),
/* int32 alerting = 15 */ buzzBeepBlink,
/* NotificationImportanceExplanation importance_source = 16 */
r.getImportanceExplanationCode(),
/* android.stats.sysui.NotificationImportance importance_initial = 18 */
/* android.stats.sysui.NotificationImportance importance_initial = 17 */
r.getInitialImportance(),
/* NotificationImportanceExplanation importance_initial_source = 19 */
/* NotificationImportanceExplanation importance_initial_source = 18 */
r.getInitialImportanceExplanationCode(),
/* android.stats.sysui.NotificationImportance importance_asst = 20 */
/* android.stats.sysui.NotificationImportance importance_asst = 19 */
r.getAssistantImportance(),
/* int32 assistant_hash = 21 */ p.getAssistantHash(),
/* float assistant_ranking_score = 22 */ 0 // TODO connect up ranking score
/* int32 assistant_hash = 20 */ p.getAssistantHash(),
/* float assistant_ranking_score = 21 */ 0 // TODO connect up ranking score
);
}

View File

@@ -0,0 +1,119 @@
/*
* 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.server.notification;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.app.Notification;
import android.app.NotificationChannel;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.UiServiceTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class NotificationRecordLoggerTest extends UiServiceTestCase {
private static final int UID = 9999;
private static final String CHANNEL_ID = "NotificationRecordLoggerTestChannelId";
private NotificationRecord getNotification(int id, String tag) {
final String packageName = mContext.getPackageName();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, CHANNEL_ID, IMPORTANCE_DEFAULT);
Notification.Builder nb = new Notification.Builder(mContext, channel.getId());
StatusBarNotification sbn = new StatusBarNotification(packageName, packageName, id, tag,
UID, 0, nb.build(), new UserHandle(UID), null,
0);
return new NotificationRecord(mContext, sbn, channel);
}
private NotificationRecordLogger.NotificationRecordPair getNotificationRecordPair(int id,
String tag) {
return new NotificationRecordLogger.NotificationRecordPair(getNotification(id, tag),
null);
}
@Test
public void testSmallHash() {
assertEquals(0, NotificationRecordLogger.NotificationRecordPair.smallHash(0));
final int maxHash = NotificationRecordLogger.NotificationRecordPair.MAX_HASH;
assertEquals(0,
NotificationRecordLogger.NotificationRecordPair.smallHash(maxHash));
assertEquals(0,
NotificationRecordLogger.NotificationRecordPair.smallHash(17 * maxHash));
assertEquals(maxHash - 1,
NotificationRecordLogger.NotificationRecordPair.smallHash(maxHash - 1));
assertEquals(maxHash - 1,
NotificationRecordLogger.NotificationRecordPair.smallHash(-1));
}
@Test
public void testGetNotificationIdHash() {
assertEquals(0,
getNotificationRecordPair(0, null).getNotificationIdHash());
assertEquals(1,
getNotificationRecordPair(1, null).getNotificationIdHash());
assertEquals(NotificationRecordLogger.NotificationRecordPair.MAX_HASH - 1,
getNotificationRecordPair(-1, null).getNotificationIdHash());
final String tag = "someTag";
final int hash = NotificationRecordLogger.NotificationRecordPair.smallHash(tag.hashCode());
assertEquals(hash, getNotificationRecordPair(0, tag).getNotificationIdHash());
// We xor the tag and hashcode together before compressing the range. The order of
// operations doesn't matter if id is small.
assertEquals(1 ^ hash,
getNotificationRecordPair(1, tag).getNotificationIdHash());
// But it does matter for an id with more 1 bits than fit in the small hash.
assertEquals(
NotificationRecordLogger.NotificationRecordPair.smallHash(-1 ^ tag.hashCode()),
getNotificationRecordPair(-1, tag).getNotificationIdHash());
assertNotEquals(-1 ^ hash,
NotificationRecordLogger.NotificationRecordPair.smallHash(-1 ^ tag.hashCode()));
}
@Test
public void testGetChannelIdHash() {
assertEquals(
NotificationRecordLogger.NotificationRecordPair.smallHash(CHANNEL_ID.hashCode()),
getNotificationRecordPair(0, null).getChannelIdHash());
assertNotEquals(
NotificationRecordLogger.NotificationRecordPair.smallHash(CHANNEL_ID.hashCode()),
CHANNEL_ID.hashCode());
}
@Test
public void testGetGroupIdHash() {
NotificationRecordLogger.NotificationRecordPair p = getNotificationRecordPair(
0, null);
assertEquals(0, p.getGroupIdHash());
final String group = "someGroup";
p.r.setOverrideGroupKey(group);
assertEquals(
NotificationRecordLogger.NotificationRecordPair.smallHash(group.hashCode()),
p.getGroupIdHash());
}
}