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

Commit 166e81fe authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents dc3391f6 7614f696
Loading
Loading
Loading
Loading
+17 −19
Original line number Diff line number Diff line
@@ -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 {
+35 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+17 −18
Original line number Diff line number Diff line
@@ -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
        );
    }

+119 −0
Original line number Diff line number Diff line
/*
 * 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());
    }
}