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

Commit c65656ae authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Do not show blocking helper if user likes channel

If a user has previously explicitly set the importance of
a notification, assume the user sentiment is postive regardless of what
the assistant suggests.

Test: runtest systemui,  runtest systemui-notification
Change-Id: I646f0878fb5bb2a28ba17fd0ec11c8cdb64b611d
Fixes: 73231297
parent 9036a88d
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;

import java.lang.IllegalArgumentException;
import java.util.List;
import java.util.Set;

@@ -274,7 +273,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    }

    private void saveImportance() {
        if (mNonblockable || !hasImportanceChanged()) {
        if (mNonblockable) {
            return;
        }
        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
@@ -409,7 +408,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        final int centerY = v.getHeight() / 2;
        final int x = targetLoc[0] - parentLoc[0] + centerX;
        final int y = targetLoc[1] - parentLoc[1] + centerY;
        mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
        mGutsContainer.closeControls(x, y, true /* save */, false /* force */);
    }

    @Override
@@ -429,7 +428,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G

    @Override
    public boolean handleCloseControls(boolean save, boolean force) {
        if (save && hasImportanceChanged()) {
        // Save regardless of the importance so we can lock the importance field if the user wants
        // to keep getting notifications
        if (save) {
            if (mCheckSaveListener != null) {
                mCheckSaveListener.checkSave(this::saveImportance, mSbn);
            } else {
+29 −8
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.systemui.statusbar;

import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
@@ -95,6 +97,7 @@ public class NotificationInfoTest extends SysuiTestCase {
        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
                null);
        mNotificationInfo.setGutsParent(mock(NotificationGuts.class));

        // PackageManager must return a packageInfo and applicationInfo.
        final PackageInfo packageInfo = new PackageInfo();
@@ -323,24 +326,27 @@ public class NotificationInfoTest extends SysuiTestCase {
    @Test
    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
            throws Exception {
        int originalImportance = mNotificationChannel.getImportance();
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.handleCloseControls(true, false);
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), any());
        assertEquals(originalImportance, mNotificationChannel.getImportance());
    }

    @Test
    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
            throws Exception {
        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.handleCloseControls(true, false);
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), any());
        assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
    }

    @Test
@@ -370,16 +376,30 @@ public class NotificationInfoTest extends SysuiTestCase {
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue((updated.getValue().getUserLockedFields()
                & NotificationChannel.USER_LOCKED_IMPORTANCE) != 0);
                & USER_LOCKED_IMPORTANCE) != 0);
    }

    @Test
    public void testBlockUndoDoesNotCallUpdateNotificationChannel() throws Exception {
    public void testKeepUpdatesNotificationChannel() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
                Collections.singleton(TEST_PACKAGE_NAME));
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.handleCloseControls(true, false);

        ArgumentCaptor<NotificationChannel> updated =
                ArgumentCaptor.forClass(NotificationChannel.class);
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
    }

    @Test
    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
        mNotificationChannel.setImportance(IMPORTANCE_LOW);
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, null);

        mNotificationInfo.findViewById(R.id.block).performClick();
        waitForUndoButton();
@@ -389,8 +409,9 @@ public class NotificationInfoTest extends SysuiTestCase {

        ArgumentCaptor<NotificationChannel> updated =
                ArgumentCaptor.forClass(NotificationChannel.class);
        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                anyString(), eq(TEST_UID), updated.capture());
        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
    }

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

import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
@@ -22,6 +23,8 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.service.notification.NotificationListenerService.Ranking
        .USER_SENTIMENT_NEUTRAL;
import static android.service.notification.NotificationListenerService.Ranking
        .USER_SENTIMENT_POSITIVE;

import android.app.Notification;
import android.app.NotificationChannel;
@@ -163,6 +166,7 @@ public final class NotificationRecord {
        mLight = calculateLights();
        mAdjustments = new ArrayList<>();
        mStats = new NotificationStats();
        calculateUserSentiment();
    }

    private boolean isPreChannelsNotification() {
@@ -320,7 +324,7 @@ public final class NotificationRecord {
        if (mPreChannelsNotification
                && (importance == IMPORTANCE_UNSPECIFIED
                || (getChannel().getUserLockedFields()
                & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0)) {
                & USER_LOCKED_IMPORTANCE) == 0)) {
            if (!stats.isNoisy && requestedImportance > IMPORTANCE_LOW) {
                requestedImportance = IMPORTANCE_LOW;
            }
@@ -585,12 +589,16 @@ public final class NotificationRecord {
                    setOverrideGroupKey(groupOverrideKey);
                }
                if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) {
                    // Only allow user sentiment update from assistant if user hasn't already
                    // expressed a preference for this channel
                    if ((getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) {
                        setUserSentiment(adjustment.getSignals().getInt(
                                Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL));
                    }
                }
            }
        }
    }

    public void setContactAffinity(float contactAffinity) {
        mContactAffinity = contactAffinity;
@@ -845,10 +853,6 @@ public final class NotificationRecord {
        }
    }

    public boolean isImportanceFromUser() {
        return mImportance == mUserImportance;
    }

    public NotificationChannel getChannel() {
        return mChannel;
    }
@@ -857,6 +861,7 @@ public final class NotificationRecord {
        if (channel != null) {
            mChannel = channel;
            calculateImportance();
            calculateUserSentiment();
        }
    }

@@ -900,6 +905,12 @@ public final class NotificationRecord {
        mSnoozeCriteria = snoozeCriteria;
    }

    private void calculateUserSentiment() {
        if ((getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0) {
            mUserSentiment = USER_SENTIMENT_POSITIVE;
        }
    }

    private void setUserSentiment(int userSentiment) {
        mUserSentiment = userSentiment;
    }
+4 −2
Original line number Diff line number Diff line
@@ -640,9 +640,11 @@ public class RankingHelper implements RankingConfig {
        if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
            updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
        }
        if (!fromUser) {
            updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
        updatedChannel.lockFields(channel.getUserLockedFields());
        }
        if (fromUser) {
            updatedChannel.lockFields(channel.getUserLockedFields());
            lockFieldsForUpdate(channel, updatedChannel);
        }
        r.channels.put(updatedChannel.getId(), updatedChannel);
+24 −2
Original line number Diff line number Diff line
@@ -15,10 +15,13 @@
 */
package com.android.server.notification;

import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.service.notification.NotificationListenerService.Ranking
        .USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking
        .USER_SENTIMENT_NEUTRAL;
import static android.service.notification.NotificationListenerService.Ranking
        .USER_SENTIMENT_POSITIVE;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -315,7 +318,7 @@ public class NotificationRecordTest extends UiServiceTestCase {
    @Test
    public void testImportance_locked_preUpgrade() throws Exception {
        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
        defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
        defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                false /* lights */, false /* defaultLights */, null /* group */);
@@ -327,7 +330,7 @@ public class NotificationRecordTest extends UiServiceTestCase {
    @Test
    public void testImportance_locked_unspecified_preUpgrade() throws Exception {
        defaultChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
        defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
        defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                false /* lights */, false /* defaultLights */, null /* group */);
@@ -549,4 +552,23 @@ public class NotificationRecordTest extends UiServiceTestCase {

        assertEquals(USER_SENTIMENT_NEGATIVE, record.getUserSentiment());
    }

    @Test
    public void testUserSentiment_userLocked() throws Exception {
        channel.lockFields(USER_LOCKED_IMPORTANCE);
        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(USER_SENTIMENT_POSITIVE, record.getUserSentiment());

        Bundle signals = new Bundle();
        signals.putInt(Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
        record.addAdjustment(new Adjustment(pkg, record.getKey(), signals, null, sbn.getUserId()));

        record.applyAdjustments();

        assertEquals(USER_SENTIMENT_POSITIVE, record.getUserSentiment());
    }
}
Loading