From a00fb9ba1cc99223f78980d84b4addb2ab05bb88 Mon Sep 17 00:00:00 2001 From: Ioana Alexandru Date: Mon, 6 Feb 2023 14:12:09 +0000 Subject: [PATCH] Allow NAS to mark when sensitive notification content was detected. Bug: 268019420 Test: NotificationListenerServiceTest Test: NotificationRecordExtractorDataTest Test: NotificationRecordTest Test: CTS in same topic Change-Id: I5741aa01993cd31b551e07f4969e8d115e56671d --- core/api/system-current.txt | 2 + .../service/notification/Adjustment.java | 9 ++- .../NotificationListenerService.java | 28 ++++++-- .../statusbar/NotificationListener.java | 49 ++++++------- .../collection/TargetSdkResolverTest.kt | 34 ++++++--- .../systemui/statusbar/RankingBuilder.java | 10 ++- .../NotificationManagerService.java | 6 +- .../notification/NotificationRecord.java | 15 ++++ .../NotificationRecordExtractorData.java | 10 ++- .../server/people/data/DataManagerTest.java | 70 ++++++++++++++----- .../NotificationListenerServiceTest.java | 11 ++- .../NotificationRecordExtractorDataTest.java | 49 ++++++++++--- .../notification/NotificationRecordTest.java | 18 +++++ 13 files changed, 238 insertions(+), 73 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 0476d7916a38b..bb095b39830f2 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -12063,6 +12063,7 @@ package android.service.notification { field public static final String KEY_NOT_CONVERSATION = "key_not_conversation"; field public static final String KEY_PEOPLE = "key_people"; field public static final String KEY_RANKING_SCORE = "key_ranking_score"; + field public static final String KEY_SENSITIVE_CONTENT = "key_sensitive_content"; field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria"; field public static final String KEY_TEXT_REPLIES = "key_text_replies"; field public static final String KEY_USER_SENTIMENT = "key_user_sentiment"; @@ -12102,6 +12103,7 @@ package android.service.notification { public static class NotificationListenerService.Ranking { method public int getProposedImportance(); + method public boolean hasSensitiveContent(); } public final class NotificationStats implements android.os.Parcelable { diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java index df185ee14e986..38076858084c0 100644 --- a/core/java/android/service/notification/Adjustment.java +++ b/core/java/android/service/notification/Adjustment.java @@ -52,7 +52,7 @@ public final class Adjustment implements Parcelable { /** @hide */ @StringDef (prefix = { "KEY_" }, value = { KEY_CONTEXTUAL_ACTIONS, KEY_GROUP_KEY, KEY_IMPORTANCE, KEY_PEOPLE, KEY_SNOOZE_CRITERIA, - KEY_TEXT_REPLIES, KEY_USER_SENTIMENT, KEY_IMPORTANCE_PROPOSAL + KEY_TEXT_REPLIES, KEY_USER_SENTIMENT, KEY_IMPORTANCE_PROPOSAL, KEY_SENSITIVE_CONTENT }) @Retention(RetentionPolicy.SOURCE) public @interface Keys {} @@ -133,6 +133,13 @@ public final class Adjustment implements Parcelable { */ public static final String KEY_IMPORTANCE_PROPOSAL = "key_importance_proposal"; + /** + * Data type: boolean, when true it suggests that the content text of this notification is + * sensitive. A notification listener can use this information to redact notifications on locked + * devices. + */ + public static final String KEY_SENSITIVE_CONTENT = "key_sensitive_content"; + /** * Data type: float, a ranking score from 0 (lowest) to 1 (highest). * Used to rank notifications inside that fall under the same classification (i.e. alerting, diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 11e51ad924067..4bc0d22578074 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1732,10 +1732,13 @@ public abstract class NotificationListenerService extends Service { private boolean mIsBubble; // Notification assistant importance suggestion private int mProposedImportance; + // Sensitive info detected by the notification assistant + private boolean mSensitiveContent; private static final int PARCEL_VERSION = 2; - public Ranking() { } + public Ranking() { + } // You can parcel it, but it's not Parcelable /** @hide */ @@ -1770,6 +1773,7 @@ public abstract class NotificationListenerService extends Service { out.writeInt(mRankingAdjustment); out.writeBoolean(mIsBubble); out.writeInt(mProposedImportance); + out.writeBoolean(mSensitiveContent); } /** @hide */ @@ -1809,6 +1813,7 @@ public abstract class NotificationListenerService extends Service { mRankingAdjustment = in.readInt(); mIsBubble = in.readBoolean(); mProposedImportance = in.readInt(); + mSensitiveContent = in.readBoolean(); } @@ -1917,6 +1922,17 @@ public abstract class NotificationListenerService extends Service { return mProposedImportance; } + /** + * Returns true if the notification text is sensitive (e.g. containing an OTP). + * + * @return whether the notification contains sensitive content + * @hide + */ + @SystemApi + public boolean hasSensitiveContent() { + return mSensitiveContent; + } + /** * If the system has overridden the group key, then this will be non-null, and this * key should be used to bundle notifications. @@ -2081,7 +2097,8 @@ public abstract class NotificationListenerService extends Service { boolean noisy, ArrayList smartActions, ArrayList smartReplies, boolean canBubble, boolean isTextChanged, boolean isConversation, ShortcutInfo shortcutInfo, - int rankingAdjustment, boolean isBubble, int proposedImportance) { + int rankingAdjustment, boolean isBubble, int proposedImportance, + boolean sensitiveContent) { mKey = key; mRank = rank; mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW; @@ -2108,6 +2125,7 @@ public abstract class NotificationListenerService extends Service { mRankingAdjustment = rankingAdjustment; mIsBubble = isBubble; mProposedImportance = proposedImportance; + mSensitiveContent = sensitiveContent; } /** @@ -2149,7 +2167,8 @@ public abstract class NotificationListenerService extends Service { other.mShortcutInfo, other.mRankingAdjustment, other.mIsBubble, - other.mProposedImportance); + other.mProposedImportance, + other.mSensitiveContent); } /** @@ -2209,7 +2228,8 @@ public abstract class NotificationListenerService extends Service { (other.mShortcutInfo == null ? 0 : other.mShortcutInfo.getId())) && Objects.equals(mRankingAdjustment, other.mRankingAdjustment) && Objects.equals(mIsBubble, other.mIsBubble) - && Objects.equals(mProposedImportance, other.mProposedImportance); + && Objects.equals(mProposedImportance, other.mProposedImportance) + && Objects.equals(mSensitiveContent, other.mSensitiveContent); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index 7d0ac1874056f..59f59aef7e469 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -268,30 +268,31 @@ public class NotificationListener extends NotificationListenerWithPlugins implem if (!rankingMap.getRanking(key, ranking)) { ranking.populate( key, - 0, - false, - 0, - 0, - 0, - null, - null, - null, - new ArrayList<>(), - new ArrayList<>(), - false, - 0, - false, - 0, - false, - new ArrayList<>(), - new ArrayList<>(), - false, - false, - false, - null, - 0, - false, - 0 + /* rank= */ 0, + /* matchesInterruptionFilter= */ false, + /* visibilityOverride= */ 0, + /* suppressedVisualEffects= */ 0, + /* importance= */ 0, + /* explanation= */ null, + /* overrideGroupKey= */ null, + /* channel= */ null, + /* overridePeople= */ new ArrayList<>(), + /* snoozeCriteria= */ new ArrayList<>(), + /* showBadge= */ false, + /* userSentiment= */ 0, + /* hidden= */ false, + /* lastAudiblyAlertedMs= */ 0, + /* noisy= */ false, + /* smartActions= */ new ArrayList<>(), + /* smartReplies= */ new ArrayList<>(), + /* canBubble= */ false, + /* isTextChanged= */ false, + /* isConversation= */ false, + /* shortcutInfo= */ null, + /* rankingAdjustment= */ 0, + /* isBubble= */ false, + /* proposedImportance= */ 0, + /* sensitiveContent= */ false ); } return ranking; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt index 9b3626bfc9ace..4708350c1c0a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt @@ -120,13 +120,31 @@ class TargetSdkResolverTest : SysuiTestCase() { private fun createRanking(key: String) = Ranking().apply { populate( key, - 0, - false, - 0, - 0, - NotificationManager.IMPORTANCE_DEFAULT, - null, null, - null, null, null, true, 0, false, -1, false, null, null, false, false, - false, null, 0, false, 0) + /* rank = */ 0, + /* matchesInterruptionFilter = */ false, + /* visibilityOverride = */ 0, + /* suppressedVisualEffects = */ 0, + /* importance = */ NotificationManager.IMPORTANCE_DEFAULT, + /* explanation = */ null, + /* overrideGroupKey = */ null, + /* channel = */ null, + /* overridePeople = */ null, + /* snoozeCriteria = */ null, + /* showBadge = */ true, + /* userSentiment = */ 0, + /* hidden = */ false, + /* lastAudiblyAlertedMs = */ -1, + /* noisy = */ false, + /* smartActions = */ null, + /* smartReplies = */ null, + /* canBubble = */ false, + /* isTextChanged = */ false, + /* isConversation = */ false, + /* shortcutInfo = */ null, + /* rankingAdjustment = */ 0, + /* isBubble = */ false, + /* proposedImportance = */ 0, + /* sensitiveContent = */ false + ) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java index 7bcad456ff6e5..6cd6594c3404c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/RankingBuilder.java @@ -60,6 +60,7 @@ public class RankingBuilder { private int mRankingAdjustment = 0; private boolean mIsBubble = false; private int mProposedImportance = IMPORTANCE_UNSPECIFIED; + private boolean mSensitiveContent = false; public RankingBuilder() { } @@ -90,6 +91,7 @@ public class RankingBuilder { mRankingAdjustment = ranking.getRankingAdjustment(); mIsBubble = ranking.isBubble(); mProposedImportance = ranking.getProposedImportance(); + mSensitiveContent = ranking.hasSensitiveContent(); } public Ranking build() { @@ -119,7 +121,8 @@ public class RankingBuilder { mShortcutInfo, mRankingAdjustment, mIsBubble, - mProposedImportance); + mProposedImportance, + mSensitiveContent); return ranking; } @@ -224,6 +227,11 @@ public class RankingBuilder { return this; } + public RankingBuilder setSensitiveContent(boolean sensitiveContent) { + mSensitiveContent = sensitiveContent; + return this; + } + public RankingBuilder setUserSentiment(int userSentiment) { mUserSentiment = userSentiment; return this; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 14ae2a749a143..62453bc21e445 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -8619,7 +8619,8 @@ public class NotificationManagerService extends SystemService { r.getImportance(), r.getRankingScore(), r.isConversation(), - r.getProposedImportance()); + r.getProposedImportance(), + r.hasSensitiveContent()); extractorDataBefore.put(r.getKey(), extractorData); mRankingHelper.extractSignals(r); } @@ -9915,7 +9916,8 @@ public class NotificationManagerService extends SystemService { ? RANKING_UNCHANGED : (record.getRankingScore() > 0 ? RANKING_PROMOTED : RANKING_DEMOTED), record.getNotification().isBubbleNotification(), - record.getProposedImportance() + record.getProposedImportance(), + record.hasSensitiveContent() ); rankings.add(ranking); } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 91b5afe1f0306..2ea6c4019c5c9 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -211,6 +211,7 @@ public final class NotificationRecord { // are sorted. private boolean mPendingLogUpdate = false; private int mProposedImportance = IMPORTANCE_UNSPECIFIED; + private boolean mSensitiveContent = false; public NotificationRecord(Context context, StatusBarNotification sbn, NotificationChannel channel) { @@ -503,6 +504,7 @@ public final class NotificationRecord { pw.println(prefix + "mProposedImportance=" + NotificationListenerService.Ranking.importanceToString(mProposedImportance)); pw.println(prefix + "mIsAppImportanceLocked=" + mIsAppImportanceLocked); + pw.println(prefix + "mSensitiveContent=" + mSensitiveContent); pw.println(prefix + "mIntercept=" + mIntercept); pw.println(prefix + "mHidden==" + mHidden); pw.println(prefix + "mGlobalSortKey=" + mGlobalSortKey); @@ -747,6 +749,12 @@ public final class NotificationRecord { Adjustment.KEY_IMPORTANCE_PROPOSAL, Integer.toString(mProposedImportance)); } + if (signals.containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) { + mSensitiveContent = signals.getBoolean(Adjustment.KEY_SENSITIVE_CONTENT); + EventLogTags.writeNotificationAdjusted(getKey(), + Adjustment.KEY_SENSITIVE_CONTENT, + Boolean.toString(mSensitiveContent)); + } if (!signals.isEmpty() && adjustment.getIssuer() != null) { mAdjustmentIssuer = adjustment.getIssuer(); } @@ -883,6 +891,13 @@ public final class NotificationRecord { return mProposedImportance; } + /** + * @return true if the notification contains sensitive content detected by the assistant. + */ + public boolean hasSensitiveContent() { + return mSensitiveContent; + } + public float getRankingScore() { return mRankingScore; } diff --git a/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java b/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java index 6dc9029f89288..3f4f7d3bbc383 100644 --- a/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java +++ b/services/core/java/com/android/server/notification/NotificationRecordExtractorData.java @@ -46,6 +46,7 @@ public final class NotificationRecordExtractorData { private final float mRankingScore; private final boolean mIsConversation; private final int mProposedImportance; + private final boolean mSensitiveContent; NotificationRecordExtractorData(int position, int visibility, boolean showBadge, boolean allowBubble, boolean isBubble, NotificationChannel channel, String groupKey, @@ -53,7 +54,7 @@ public final class NotificationRecordExtractorData { Integer userSentiment, Integer suppressVisually, ArrayList systemSmartActions, ArrayList smartReplies, int importance, float rankingScore, - boolean isConversation, int proposedImportance) { + boolean isConversation, int proposedImportance, boolean sensitiveContent) { mPosition = position; mVisibility = visibility; mShowBadge = showBadge; @@ -71,6 +72,7 @@ public final class NotificationRecordExtractorData { mRankingScore = rankingScore; mIsConversation = isConversation; mProposedImportance = proposedImportance; + mSensitiveContent = sensitiveContent; } // Returns whether the provided NotificationRecord differs from the cached data in any way. @@ -90,7 +92,8 @@ public final class NotificationRecordExtractorData { || !Objects.equals(mSystemSmartActions, r.getSystemGeneratedSmartActions()) || !Objects.equals(mSmartReplies, r.getSmartReplies()) || mImportance != r.getImportance() - || mProposedImportance != r.getProposedImportance(); + || mProposedImportance != r.getProposedImportance() + || mSensitiveContent != r.hasSensitiveContent(); } // Returns whether the NotificationRecord has a change from this data for which we should @@ -113,6 +116,7 @@ public final class NotificationRecordExtractorData { || mImportance != r.getImportance() || !r.rankingScoreMatches(mRankingScore) || mIsConversation != r.isConversation() - || mProposedImportance != r.getProposedImportance(); + || mProposedImportance != r.getProposedImportance() + || mSensitiveContent != r.hasSensitiveContent(); } } diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java index 93f6db7e93869..9fc46c5638416 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java @@ -1737,15 +1737,33 @@ public final class DataManagerTest { NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking) invocationOnMock.getArguments()[1]; ranking.populate( - (String) invocationOnMock.getArguments()[0], - 0, - false, - 0, - 0, + /* key= */ (String) invocationOnMock.getArguments()[0], + /* rank= */ 0, + /* matchesInterruptionFilter= */ false, + /* visibilityOverride= */ 0, + /* suppressedVisualEffects= */ 0, mParentNotificationChannel.getImportance(), - null, null, - mParentNotificationChannel, null, null, true, 0, false, -1, false, null, null, - false, false, false, null, 0, false, 0); + /* explanation= */ null, + /* overrideGroupKey= */ null, + mParentNotificationChannel, + /* overridePeople= */ null, + /* snoozeCriteria= */ null, + /* showBadge= */ true, + /* userSentiment= */ 0, + /* hidden= */ false, + /* lastAudiblyAlertedMs= */ -1, + /* noisy= */ false, + /* smartActions= */ null, + /* smartReplies= */ null, + /* canBubble= */ false, + /* isTextChanged= */ false, + /* isConversation= */ false, + /* shortcutInfo= */ null, + /* rankingAdjustment= */ 0, + /* isBubble= */ false, + /* proposedImportance= */ 0, + /* sensitiveContent= */ false + ); return true; }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class)); @@ -1763,15 +1781,33 @@ public final class DataManagerTest { NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking) invocationOnMock.getArguments()[1]; ranking.populate( - (String) invocationOnMock.getArguments()[0], - 0, - false, - 0, - 0, - mNotificationChannel.getImportance(), - null, null, - mNotificationChannel, null, null, true, 0, false, -1, false, null, null, false, - false, false, null, 0, false, 0); + /* key= */ (String) invocationOnMock.getArguments()[0], + /* rank= */ 0, + /* matchesInterruptionFilter= */ false, + /* visibilityOverride= */ 0, + /* suppressedVisualEffects= */ 0, + mParentNotificationChannel.getImportance(), + /* explanation= */ null, + /* overrideGroupKey= */ null, + mParentNotificationChannel, + /* overridePeople= */ null, + /* snoozeCriteria= */ null, + /* showBadge= */ true, + /* userSentiment= */ 0, + /* hidden= */ false, + /* lastAudiblyAlertedMs= */ -1, + /* noisy= */ false, + /* smartActions= */ null, + /* smartReplies= */ null, + /* canBubble= */ false, + /* isTextChanged= */ false, + /* isConversation= */ false, + /* shortcutInfo= */ null, + /* rankingAdjustment= */ 0, + /* isBubble= */ false, + /* proposedImportance= */ 0, + /* sensitiveContent= */ false + ); return true; }).when(mRankingMap).getRanking(eq(CUSTOM_KEY), any(NotificationListenerService.Ranking.class)); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java index 8a99c2cdcc6f6..2f7a5f4e0453d 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java @@ -194,7 +194,8 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { tweak.getConversationShortcutInfo(), tweak.getRankingAdjustment(), tweak.isBubble(), - tweak.getProposedImportance() + tweak.getProposedImportance(), + tweak.hasSensitiveContent() ); assertNotEquals(nru, nru2); } @@ -276,7 +277,8 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { getShortcutInfo(i), getRankingAdjustment(i), isBubble(i), - getProposedImportance(i) + getProposedImportance(i), + hasSensitiveContent(i) ); rankings[i] = ranking; } @@ -408,6 +410,10 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { return index % 5 - 1; } + private boolean hasSensitiveContent(int index) { + return index % 3 == 0; + } + private boolean isBubble(int index) { return index % 4 == 0; } @@ -450,6 +456,7 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { b.getConversationShortcutInfo().getId()); assertActionsEqual(a.getSmartActions(), b.getSmartActions()); assertEquals(a.getProposedImportance(), b.getProposedImportance()); + assertEquals(a.hasSensitiveContent(), b.hasSensitiveContent()); } private void detailedAssertEquals(RankingMap a, RankingMap b) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java index 87e86cb00f568..e6569f7e0ce22 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java @@ -19,29 +19,20 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; -import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import android.app.Notification; import android.app.NotificationChannel; -import android.app.PendingIntent; -import android.content.Intent; -import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.UserHandle; import android.service.notification.Adjustment; -import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import com.android.server.UiServiceTestCase; import org.junit.Test; -import java.util.ArrayList; -import java.util.Objects; - public class NotificationRecordExtractorDataTest extends UiServiceTestCase { @Test @@ -65,7 +56,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase { r.getImportance(), r.getRankingScore(), r.isConversation(), - r.getProposedImportance()); + r.getProposedImportance(), + r.hasSensitiveContent()); assertFalse(extractorData.hasDiffForRankingLocked(r, 1)); assertFalse(extractorData.hasDiffForLoggingLocked(r, 1)); @@ -92,7 +84,8 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase { r.getImportance(), r.getRankingScore(), r.isConversation(), - r.getProposedImportance()); + r.getProposedImportance(), + r.hasSensitiveContent()); Bundle signals = new Bundle(); signals.putInt(Adjustment.KEY_IMPORTANCE_PROPOSAL, IMPORTANCE_HIGH); @@ -104,6 +97,40 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase { assertTrue(extractorData.hasDiffForLoggingLocked(r, 1)); } + @Test + public void testHasDiffs_sensitiveContentChange() { + NotificationRecord r = generateRecord(); + + NotificationRecordExtractorData extractorData = new NotificationRecordExtractorData( + 1, + r.getPackageVisibilityOverride(), + r.canShowBadge(), + r.canBubble(), + r.getNotification().isBubbleNotification(), + r.getChannel(), + r.getGroupKey(), + r.getPeopleOverride(), + r.getSnoozeCriteria(), + r.getUserSentiment(), + r.getSuppressedVisualEffects(), + r.getSystemGeneratedSmartActions(), + r.getSmartReplies(), + r.getImportance(), + r.getRankingScore(), + r.isConversation(), + r.getProposedImportance(), + r.hasSensitiveContent()); + + Bundle signals = new Bundle(); + signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, true); + Adjustment adjustment = new Adjustment("pkg", r.getKey(), signals, "", 0); + r.addAdjustment(adjustment); + r.applyAdjustments(); + + assertTrue(extractorData.hasDiffForRankingLocked(r, 1)); + assertTrue(extractorData.hasDiffForLoggingLocked(r, 1)); + } + private NotificationRecord generateRecord() { NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW); final Notification.Builder builder = new Notification.Builder(getContext()) diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java index 14b004827ecea..25e74bf5dcd21 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java @@ -787,6 +787,24 @@ public class NotificationRecordTest extends UiServiceTestCase { assertFalse(record.getIsAppImportanceLocked()); } + @Test + public void testSensitiveContent() { + StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */, + true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /* defaultLights */, groupId /* group */); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); + + assertFalse(record.hasSensitiveContent()); + + Bundle signals = new Bundle(); + signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, true); + record.addAdjustment(new Adjustment(mPkg, record.getKey(), signals, null, sbn.getUserId())); + + record.applyAdjustments(); + + assertTrue(record.hasSensitiveContent()); + } + @Test public void testIsInterruptive_textChanged_notSeen() { StatusBarNotification sbn = getNotification(PKG_O, false /* noisy */,