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

Commit d4d9b233 authored by Daniel Sandler's avatar Daniel Sandler Committed by Android (Google) Code Review
Browse files

Merge "Dramatically simplify NotificationRankingUpdate." into qt-dev

parents bc276072 ba666f8f
Loading
Loading
Loading
Loading
+192 −388

File changed.

Preview size limit exceeded, changes collapsed.

+18 −154
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package android.service.notification;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

@@ -23,73 +22,18 @@ import android.os.Parcelable;
 * @hide
 */
public class NotificationRankingUpdate implements Parcelable {
    // TODO: Support incremental updates.
    private final String[] mKeys;
    private final String[] mInterceptedKeys;
    private final Bundle mVisibilityOverrides;
    private final Bundle mSuppressedVisualEffects;
    private final int[] mImportance;
    private final Bundle mImportanceExplanation;
    private final Bundle mOverrideGroupKeys;
    private final Bundle mChannels;
    private final Bundle mOverridePeople;
    private final Bundle mSnoozeCriteria;
    private final Bundle mShowBadge;
    private final Bundle mUserSentiment;
    private final Bundle mHidden;
    private final Bundle mSmartActions;
    private final Bundle mSmartReplies;
    private final Bundle mLastAudiblyAlerted;
    private final Bundle mNoisy;
    private final boolean[] mCanBubble;
    private final NotificationListenerService.RankingMap mRankingMap;

    public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
            Bundle visibilityOverrides, Bundle suppressedVisualEffects,
            int[] importance, Bundle explanation, Bundle overrideGroupKeys,
            Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
            Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
            Bundle smartReplies, Bundle lastAudiblyAlerted, Bundle noisy, boolean[] canBubble) {
        mKeys = keys;
        mInterceptedKeys = interceptedKeys;
        mVisibilityOverrides = visibilityOverrides;
        mSuppressedVisualEffects = suppressedVisualEffects;
        mImportance = importance;
        mImportanceExplanation = explanation;
        mOverrideGroupKeys = overrideGroupKeys;
        mChannels = channels;
        mOverridePeople = overridePeople;
        mSnoozeCriteria = snoozeCriteria;
        mShowBadge = showBadge;
        mUserSentiment = userSentiment;
        mHidden = hidden;
        mSmartActions = smartActions;
        mSmartReplies = smartReplies;
        mLastAudiblyAlerted = lastAudiblyAlerted;
        mNoisy = noisy;
        mCanBubble = canBubble;
    public NotificationRankingUpdate(NotificationListenerService.Ranking[] rankings) {
        mRankingMap = new NotificationListenerService.RankingMap(rankings);
    }

    public NotificationRankingUpdate(Parcel in) {
        mKeys = in.readStringArray();
        mInterceptedKeys = in.readStringArray();
        mVisibilityOverrides = in.readBundle();
        mSuppressedVisualEffects = in.readBundle();
        mImportance = new int[mKeys.length];
        in.readIntArray(mImportance);
        mImportanceExplanation = in.readBundle();
        mOverrideGroupKeys = in.readBundle();
        mChannels = in.readBundle();
        mOverridePeople = in.readBundle();
        mSnoozeCriteria = in.readBundle();
        mShowBadge = in.readBundle();
        mUserSentiment = in.readBundle();
        mHidden = in.readBundle();
        mSmartActions = in.readBundle();
        mSmartReplies = in.readBundle();
        mLastAudiblyAlerted = in.readBundle();
        mNoisy = in.readBundle();
        mCanBubble = new boolean[mKeys.length];
        in.readBooleanArray(mCanBubble);
        mRankingMap = in.readParcelable(getClass().getClassLoader());
    }

    public NotificationListenerService.RankingMap getRankingMap() {
        return mRankingMap;
    }

    @Override
@@ -97,26 +41,18 @@ public class NotificationRankingUpdate implements Parcelable {
        return 0;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        NotificationRankingUpdate other = (NotificationRankingUpdate) o;
        return mRankingMap.equals(other.mRankingMap);
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeStringArray(mKeys);
        out.writeStringArray(mInterceptedKeys);
        out.writeBundle(mVisibilityOverrides);
        out.writeBundle(mSuppressedVisualEffects);
        out.writeIntArray(mImportance);
        out.writeBundle(mImportanceExplanation);
        out.writeBundle(mOverrideGroupKeys);
        out.writeBundle(mChannels);
        out.writeBundle(mOverridePeople);
        out.writeBundle(mSnoozeCriteria);
        out.writeBundle(mShowBadge);
        out.writeBundle(mUserSentiment);
        out.writeBundle(mHidden);
        out.writeBundle(mSmartActions);
        out.writeBundle(mSmartReplies);
        out.writeBundle(mLastAudiblyAlerted);
        out.writeBundle(mNoisy);
        out.writeBooleanArray(mCanBubble);
        out.writeParcelable(mRankingMap, flags);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -129,76 +65,4 @@ public class NotificationRankingUpdate implements Parcelable {
            return new NotificationRankingUpdate[size];
        }
    };

    public String[] getOrderedKeys() {
        return mKeys;
    }

    public String[] getInterceptedKeys() {
        return mInterceptedKeys;
    }

    public Bundle getVisibilityOverrides() {
        return mVisibilityOverrides;
    }

    public Bundle getSuppressedVisualEffects() {
        return mSuppressedVisualEffects;
    }

    public int[] getImportance() {
        return mImportance;
    }

    public Bundle getImportanceExplanation() {
        return mImportanceExplanation;
    }

    public Bundle getOverrideGroupKeys() {
        return mOverrideGroupKeys;
    }

    public Bundle getChannels() {
        return mChannels;
    }

    public Bundle getOverridePeople() {
        return mOverridePeople;
    }

    public Bundle getSnoozeCriteria() {
        return mSnoozeCriteria;
    }

    public Bundle getShowBadge() {
        return mShowBadge;
    }

    public Bundle getUserSentiment() {
        return mUserSentiment;
    }

    public Bundle getHidden() {
        return mHidden;
    }

    public Bundle getSmartActions() {
        return mSmartActions;
    }

    public Bundle getSmartReplies() {
        return mSmartReplies;
    }

    public Bundle getLastAudiblyAlerted() {
        return mLastAudiblyAlerted;
    }

    public Bundle getNoisy() {
        return mNoisy;
    }

    public boolean[] getCanBubble() {
        return mCanBubble;
    }
}
+30 −60
Original line number Diff line number Diff line
@@ -7234,72 +7234,42 @@ public class NotificationManagerService extends SystemService {
    @GuardedBy("mNotificationLock")
    private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
        final int N = mNotificationList.size();
        ArrayList<String> keys = new ArrayList<String>(N);
        ArrayList<String> interceptedKeys = new ArrayList<String>(N);
        ArrayList<Integer> importance = new ArrayList<>(N);
        Bundle overrideGroupKeys = new Bundle();
        Bundle visibilityOverrides = new Bundle();
        Bundle suppressedVisualEffects = new Bundle();
        Bundle explanation = new Bundle();
        Bundle channels = new Bundle();
        Bundle overridePeople = new Bundle();
        Bundle snoozeCriteria = new Bundle();
        Bundle showBadge = new Bundle();
        Bundle userSentiment = new Bundle();
        Bundle hidden = new Bundle();
        Bundle systemGeneratedSmartActions = new Bundle();
        Bundle smartReplies = new Bundle();
        Bundle lastAudiblyAlerted = new Bundle();
        Bundle noisy = new Bundle();
        ArrayList<Boolean> canBubble = new ArrayList<>(N);
        final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>();

        for (int i = 0; i < N; i++) {
            NotificationRecord record = mNotificationList.get(i);
            if (!isVisibleToListener(record.sbn, info)) {
                continue;
            }
            final String key = record.sbn.getKey();
            keys.add(key);
            importance.add(record.getImportance());
            if (record.getImportanceExplanation() != null) {
                explanation.putCharSequence(key, record.getImportanceExplanation());
            }
            if (record.isIntercepted()) {
                interceptedKeys.add(key);

            }
            suppressedVisualEffects.putInt(key, record.getSuppressedVisualEffects());
            if (record.getPackageVisibilityOverride()
                    != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
                visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
            }
            overrideGroupKeys.putString(key, record.sbn.getOverrideGroupKey());
            channels.putParcelable(key, record.getChannel());
            overridePeople.putStringArrayList(key, record.getPeopleOverride());
            snoozeCriteria.putParcelableArrayList(key, record.getSnoozeCriteria());
            showBadge.putBoolean(key, record.canShowBadge());
            userSentiment.putInt(key, record.getUserSentiment());
            hidden.putBoolean(key, record.isHidden());
            systemGeneratedSmartActions.putParcelableArrayList(key,
                    record.getSystemGeneratedSmartActions());
            smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
            lastAudiblyAlerted.putLong(key, record.getLastAudiblyAlertedMs());
            noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
            canBubble.add(record.canBubble());
        }
        final int M = keys.size();
        String[] keysAr = keys.toArray(new String[M]);
        String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
        int[] importanceAr = new int[M];
        boolean[] canBubbleAr = new boolean[M];
        for (int i = 0; i < M; i++) {
            importanceAr[i] = importance.get(i);
            canBubbleAr[i] = canBubble.get(i);
        }
        return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
                suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
                systemGeneratedSmartActions, smartReplies, lastAudiblyAlerted, noisy,
                canBubbleAr);
            final NotificationListenerService.Ranking ranking =
                    new NotificationListenerService.Ranking();
            ranking.populate(
                    key,
                    rankings.size(),
                    !record.isIntercepted(),
                    record.getPackageVisibilityOverride(),
                    record.getSuppressedVisualEffects(),
                    record.getImportance(),
                    record.getImportanceExplanation(),
                    record.sbn.getOverrideGroupKey(),
                    record.getChannel(),
                    record.getPeopleOverride(),
                    record.getSnoozeCriteria(),
                    record.canShowBadge(),
                    record.getUserSentiment(),
                    record.isHidden(),
                    record.getLastAudiblyAlertedMs(),
                    record.getSound() != null || record.getVibration() != null,
                    record.getSystemGeneratedSmartActions(),
                    record.getSmartReplies(),
                    record.canBubble()
            );
            rankings.add(ranking);
        }

        return new NotificationRankingUpdate(
                rankings.toArray(new NotificationListenerService.Ranking[0]));
    }

    boolean hasCompanionDevice(ManagedServiceInfo info) {
+139 −46
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -33,10 +35,11 @@ import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.SnoozeCriterion;
import android.test.suitebuilder.annotation.SmallTest;
@@ -55,8 +58,6 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class NotificationListenerServiceTest extends UiServiceTestCase {

    private String[] mKeys = new String[] { "key", "key1", "key2", "key3", "key4"};

    @Test
    public void testGetActiveNotifications_notNull() throws Exception {
        TestListenerService service = new TestListenerService();
@@ -97,52 +98,144 @@ public class NotificationListenerServiceTest extends UiServiceTestCase {
        }
    }

    private NotificationRankingUpdate generateUpdate() {
        List<String> interceptedKeys = new ArrayList<>();
        Bundle visibilityOverrides = new Bundle();
        Bundle overrideGroupKeys = new Bundle();
        Bundle suppressedVisualEffects = new Bundle();
        Bundle explanation = new Bundle();
        Bundle channels = new Bundle();
        Bundle overridePeople = new Bundle();
        Bundle snoozeCriteria = new Bundle();
        Bundle showBadge = new Bundle();
        int[] importance = new int[mKeys.length];
        Bundle userSentiment = new Bundle();
        Bundle mHidden = new Bundle();
        Bundle smartActions = new Bundle();
        Bundle smartReplies = new Bundle();
        Bundle lastAudiblyAlerted = new Bundle();
        Bundle noisy = new Bundle();
        boolean[] canBubble = new boolean[mKeys.length];
    // Tests parceling of NotificationRankingUpdate, and by extension, RankingMap and Ranking.
    @Test
    public void testRankingUpdate_parcel() {
        NotificationRankingUpdate nru = generateUpdate();
        Parcel parcel = Parcel.obtain();
        nru.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        NotificationRankingUpdate nru1 = NotificationRankingUpdate.CREATOR.createFromParcel(parcel);
        assertEquals(nru, nru1);
    }

    private void detailedAssertEquals(RankingMap a, RankingMap b) {
        Ranking arank = new Ranking();
        Ranking brank = new Ranking();
        assertArrayEquals(a.getOrderedKeys(), b.getOrderedKeys());
        for (String key : a.getOrderedKeys()) {
            a.getRanking(key, arank);
            b.getRanking(key, brank);
            detailedAssertEquals("ranking for key <" + key + ">", arank, brank);
        }
    }

    // Tests parceling of RankingMap and RankingMap.equals
    @Test
    public void testRankingMap_parcel() {
        RankingMap rmap = generateUpdate().getRankingMap();
        Parcel parcel = Parcel.obtain();
        rmap.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        RankingMap rmap1 = RankingMap.CREATOR.createFromParcel(parcel);

        detailedAssertEquals(rmap, rmap1);
        assertEquals(rmap, rmap1);
    }

    private void detailedAssertEquals(String comment, Ranking a, Ranking b) {
        assertEquals(comment, a.getKey(), b.getKey());
        assertEquals(comment, a.getRank(), b.getRank());
        assertEquals(comment, a.matchesInterruptionFilter(), b.matchesInterruptionFilter());
        assertEquals(comment, a.getVisibilityOverride(), b.getVisibilityOverride());
        assertEquals(comment, a.getSuppressedVisualEffects(), b.getSuppressedVisualEffects());
        assertEquals(comment, a.getImportance(), b.getImportance());
        assertEquals(comment, a.getImportanceExplanation(), b.getImportanceExplanation());
        assertEquals(comment, a.getOverrideGroupKey(), b.getOverrideGroupKey());
        assertEquals(comment, a.getChannel(), b.getChannel());
        assertEquals(comment, a.getAdditionalPeople(), b.getAdditionalPeople());
        assertEquals(comment, a.getSnoozeCriteria(), b.getSnoozeCriteria());
        assertEquals(comment, a.canShowBadge(), b.canShowBadge());
        assertEquals(comment, a.getUserSentiment(), b.getUserSentiment());
        assertEquals(comment, a.isSuspended(), b.isSuspended());
        assertEquals(comment, a.getLastAudiblyAlertedMillis(), b.getLastAudiblyAlertedMillis());
        assertEquals(comment, a.isNoisy(), b.isNoisy());
        assertEquals(comment, a.getSmartReplies(), b.getSmartReplies());
        assertEquals(comment, a.canBubble(), b.canBubble());
        assertActionsEqual(a.getSmartActions(), b.getSmartActions());
    }

    // Tests parceling of Ranking and Ranking.equals
    @Test
    public void testRanking_parcel() {
        Ranking ranking = generateUpdate().getRankingMap().getRawRankingObject(mKeys[0]);
        Parcel parcel = Parcel.obtain();
        ranking.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        Ranking ranking1 = new Ranking(parcel);
        detailedAssertEquals("rankings differ: ", ranking, ranking1);
        assertEquals(ranking, ranking1);
    }

    private void detailedAssertEquals(NotificationRankingUpdate a, NotificationRankingUpdate b) {
        assertEquals(a.getRankingMap(), b.getRankingMap());
    }

    // Tests NotificationRankingUpdate.equals(), and by extension, RankingMap and Ranking.
    @Test
    public void testRankingUpdate_equals() {
        NotificationRankingUpdate nru = generateUpdate();
        NotificationRankingUpdate nru2 = generateUpdate();
        detailedAssertEquals(nru, nru2);
        assertEquals(nru, nru2);
        Ranking tweak = nru2.getRankingMap().getRawRankingObject(mKeys[0]);
        tweak.populate(
                tweak.getKey(),
                tweak.getRank(),
                !tweak.matchesInterruptionFilter(), // note the inversion here!
                tweak.getVisibilityOverride(),
                tweak.getSuppressedVisualEffects(),
                tweak.getImportance(),
                tweak.getImportanceExplanation(),
                tweak.getOverrideGroupKey(),
                tweak.getChannel(),
                (ArrayList) tweak.getAdditionalPeople(),
                (ArrayList) tweak.getSnoozeCriteria(),
                tweak.canShowBadge(),
                tweak.getUserSentiment(),
                tweak.isSuspended(),
                tweak.getLastAudiblyAlertedMillis(),
                tweak.isNoisy(),
                (ArrayList) tweak.getSmartActions(),
                (ArrayList) tweak.getSmartReplies(),
                tweak.canBubble()
        );
        assertNotEquals(nru, nru2);
    }

    // Test data

    private String[] mKeys = new String[] { "key", "key1", "key2", "key3", "key4"};

    private NotificationRankingUpdate generateUpdate() {
        Ranking[] rankings = new Ranking[mKeys.length];
        for (int i = 0; i < mKeys.length; i++) {
            String key = mKeys[i];
            visibilityOverrides.putInt(key, getVisibilityOverride(i));
            overrideGroupKeys.putString(key, getOverrideGroupKey(key));
            if (isIntercepted(i)) {
                interceptedKeys.add(key);
            }
            suppressedVisualEffects.putInt(key, getSuppressedVisualEffects(i));
            importance[i] = getImportance(i);
            explanation.putString(key, getExplanation(key));
            channels.putParcelable(key, getChannel(key, i));
            overridePeople.putStringArrayList(key, getPeople(key, i));
            snoozeCriteria.putParcelableArrayList(key, getSnoozeCriteria(key, i));
            showBadge.putBoolean(key, getShowBadge(i));
            userSentiment.putInt(key, getUserSentiment(i));
            mHidden.putBoolean(key, getHidden(i));
            smartActions.putParcelableArrayList(key, getSmartActions(key, i));
            smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
            lastAudiblyAlerted.putLong(key, lastAudiblyAlerted(i));
            noisy.putBoolean(key, getNoisy(i));
            canBubble[i] = canBubble(i);
        }
        NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
                interceptedKeys.toArray(new String[0]), visibilityOverrides,
                suppressedVisualEffects, importance, explanation, overrideGroupKeys,
                channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
                smartActions, smartReplies, lastAudiblyAlerted, noisy, canBubble);
            final String key = mKeys[i];
            Ranking ranking = new Ranking();
            ranking.populate(
                    key,
                    i,
                    !isIntercepted(i),
                    getVisibilityOverride(i),
                    getSuppressedVisualEffects(i),
                    getImportance(i),
                    getExplanation(key),
                    getOverrideGroupKey(key),
                    getChannel(key, i),
                    getPeople(key, i),
                    getSnoozeCriteria(key, i),
                    getShowBadge(i),
                    getUserSentiment(i),
                    getHidden(i),
                    lastAudiblyAlerted(i),
                    getNoisy(i),
                    getSmartActions(key, i),
                    getSmartReplies(key, i),
                    canBubble(i)
            );
            rankings[i] = ranking;
        }
        NotificationRankingUpdate update = new NotificationRankingUpdate(rankings);
        return update;
    }