Loading services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +87 −19 Original line number Diff line number Diff line Loading @@ -20,8 +20,14 @@ import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Flags.notificationForceGrouping; import android.content.Context; import android.util.ArraySet; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * Applies adjustments from the group helper and notification assistant */ Loading @@ -30,6 +36,14 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac private static final boolean DBG = false; private GroupHelper mGroupHelper; /** Length of time (in milliseconds) that a noisy notification will stay in its non-bundled * classification. */ @VisibleForTesting static final long HANG_TIME_MS = 30000; @VisibleForTesting InjectedTime mInjectedTimeMs = null; public void initialize(Context ctx, NotificationUsageStats usageStats) { if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); Loading @@ -43,12 +57,73 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE); final boolean removedClassification = record.hasAdjustment(KEY_UNCLASSIFY); if (Flags.showNoisyBundledNotifications() && android.service.notification.Flags.notificationClassification() && hasAdjustedClassification && record.getLastAudiblyAlertedMs() > 0) { record.applyAdjustments(new ArraySet<>(new String[] {KEY_TYPE})); return getClassificationReconsideration(record); } record.applyAdjustments(); if (notificationForceGrouping() && android.service.notification.Flags.notificationClassification()) { // Classification adjustments trigger regrouping if (mGroupHelper != null && (hasAdjustedClassification || removedClassification)) { return getRegroupReconsideration( record, hasAdjustedClassification, removedClassification); } } return null; } @Override public void setConfig(RankingConfig config) { // config is not used } @Override public void setZenHelper(ZenModeHelper helper) { } @Override public void setGroupHelper(GroupHelper groupHelper) { mGroupHelper = groupHelper; } private long getCurrentTime() { if (mInjectedTimeMs != null) { return mInjectedTimeMs.getCurrentTimeMillis(); } return System.currentTimeMillis(); } private RankingReconsideration getClassificationReconsideration(NotificationRecord record) { return new RankingReconsideration(record.getKey(), HANG_TIME_MS) { @Override public void work() { // pass } @Override public void applyChangesLocked(NotificationRecord record) { if ((getCurrentTime() - record.getLastAudiblyAlertedMs()) >= HANG_TIME_MS) { record.applyAdjustments(); getRegroupReconsideration(record, true, false).applyChangesLocked(record); } } }; } // The notification channel of the record has changed such that it's now moving to a new // UI section. We need to change the record's grouping to make sure it's not in a group // for the wrong section private RankingReconsideration getRegroupReconsideration(NotificationRecord record, boolean hasAdjustedClassification, boolean removedClassification) { return new RankingReconsideration(record.getKey(), 0) { @Override public void work() { Loading @@ -69,23 +144,16 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac } }; } } return null; } static class InjectedTime { private final long mCurrentTimeMillis; @Override public void setConfig(RankingConfig config) { // config is not used InjectedTime(long time) { mCurrentTimeMillis = time; } @Override public void setZenHelper(ZenModeHelper helper) { long getCurrentTimeMillis() { return mCurrentTimeMillis; } @Override public void setGroupHelper(GroupHelper groupHelper) { mGroupHelper = groupHelper; } } services/core/java/com/android/server/notification/NotificationRecord.java +128 −51 Original line number Diff line number Diff line Loading @@ -21,7 +21,20 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.service.notification.Adjustment.KEY_CONTEXTUAL_ACTIONS; import static android.service.notification.Adjustment.KEY_GROUP_KEY; import static android.service.notification.Adjustment.KEY_IMPORTANCE; import static android.service.notification.Adjustment.KEY_IMPORTANCE_PROPOSAL; import static android.service.notification.Adjustment.KEY_NOT_CONVERSATION; import static android.service.notification.Adjustment.KEY_PEOPLE; import static android.service.notification.Adjustment.KEY_RANKING_SCORE; import static android.service.notification.Adjustment.KEY_SENSITIVE_CONTENT; import static android.service.notification.Adjustment.KEY_SNOOZE_CRITERIA; import static android.service.notification.Adjustment.KEY_SUMMARIZATION; import static android.service.notification.Adjustment.KEY_TEXT_REPLIES; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE; Loading Loading @@ -708,6 +721,13 @@ public final class NotificationRecord { this.getSbn().getNotification()); } @VisibleForTesting int getPendingAdjustmentCount() { synchronized (mAdjustments) { return mAdjustments.size(); } } public boolean hasAdjustment(String key) { synchronized (mAdjustments) { for (Adjustment adjustment : mAdjustments) { Loading @@ -726,113 +746,160 @@ public final class NotificationRecord { } public void applyAdjustments() { long now = System.currentTimeMillis(); applyAdjustments(new ArraySet<>()); } public void applyAdjustments(@NonNull ArraySet<String> keysToSkip) { synchronized (mAdjustments) { for (Adjustment adjustment: mAdjustments) { for (int i = mAdjustments.size() - 1; i >= 0; i--) { Adjustment adjustment = mAdjustments.get(i); Bundle signals = adjustment.getSignals(); if (signals.containsKey(Adjustment.KEY_PEOPLE)) { if (signals.containsKey(KEY_PEOPLE) && !keysToSkip.contains(KEY_PEOPLE)) { final ArrayList<String> people = adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE); adjustment.getSignals().getStringArrayList(KEY_PEOPLE); setPeopleOverride(people); EventLogTags.writeNotificationAdjusted( getKey(), Adjustment.KEY_PEOPLE, people.toString()); EventLogTags.writeNotificationAdjusted(getKey(), KEY_PEOPLE, people.toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_PEOPLE); } if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) { } if (signals.containsKey(KEY_SNOOZE_CRITERIA) && !keysToSkip.contains(KEY_SNOOZE_CRITERIA)) { final ArrayList<SnoozeCriterion> snoozeCriterionList = adjustment.getSignals().getParcelableArrayList( Adjustment.KEY_SNOOZE_CRITERIA, KEY_SNOOZE_CRITERIA, android.service.notification.SnoozeCriterion.class); setSnoozeCriteria(snoozeCriterionList); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SNOOZE_CRITERIA, EventLogTags.writeNotificationAdjusted(getKey(), KEY_SNOOZE_CRITERIA, snoozeCriterionList.toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SNOOZE_CRITERIA); } } if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) { if (signals.containsKey(KEY_GROUP_KEY) && !keysToSkip.contains(KEY_GROUP_KEY)) { final String groupOverrideKey = adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY); adjustment.getSignals().getString(KEY_GROUP_KEY); setOverrideGroupKey(groupOverrideKey); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_GROUP_KEY, EventLogTags.writeNotificationAdjusted(getKey(), KEY_GROUP_KEY, groupOverrideKey); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_GROUP_KEY); } if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) { } if (signals.containsKey(KEY_USER_SENTIMENT) && !keysToSkip.contains(KEY_USER_SENTIMENT)) { // Only allow user sentiment update from assistant if user hasn't already // expressed a preference for this channel if (!mIsAppImportanceLocked && (getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) { setUserSentiment(adjustment.getSignals().getInt( Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL)); KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_USER_SENTIMENT, KEY_USER_SENTIMENT, Integer.toString(getUserSentiment())); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_USER_SENTIMENT); } } } if (signals.containsKey(Adjustment.KEY_CONTEXTUAL_ACTIONS)) { if (signals.containsKey(KEY_CONTEXTUAL_ACTIONS) && !keysToSkip.contains(KEY_CONTEXTUAL_ACTIONS)) { setSystemGeneratedSmartActions( signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, signals.getParcelableArrayList(KEY_CONTEXTUAL_ACTIONS, android.app.Notification.Action.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_CONTEXTUAL_ACTIONS, getSystemGeneratedSmartActions().toString()); KEY_CONTEXTUAL_ACTIONS, getSystemGeneratedSmartActions().toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_CONTEXTUAL_ACTIONS); } } if (signals.containsKey(Adjustment.KEY_TEXT_REPLIES)) { setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_TEXT_REPLIES)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TEXT_REPLIES, if (signals.containsKey(KEY_TEXT_REPLIES) && !keysToSkip.contains(KEY_TEXT_REPLIES)) { setSmartReplies(signals.getCharSequenceArrayList(KEY_TEXT_REPLIES)); EventLogTags.writeNotificationAdjusted(getKey(), KEY_TEXT_REPLIES, getSmartReplies().toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_TEXT_REPLIES); } if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) { int importance = signals.getInt(Adjustment.KEY_IMPORTANCE); } if (signals.containsKey(KEY_IMPORTANCE) && !keysToSkip.contains(KEY_IMPORTANCE)) { int importance = signals.getInt(KEY_IMPORTANCE); importance = Math.max(IMPORTANCE_UNSPECIFIED, importance); importance = Math.min(IMPORTANCE_HIGH, importance); setAssistantImportance(importance); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_IMPORTANCE, EventLogTags.writeNotificationAdjusted(getKey(), KEY_IMPORTANCE, Integer.toString(importance)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_IMPORTANCE); } } if (signals.containsKey(Adjustment.KEY_RANKING_SCORE)) { mRankingScore = signals.getFloat(Adjustment.KEY_RANKING_SCORE); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_RANKING_SCORE, if (signals.containsKey(KEY_RANKING_SCORE) && !keysToSkip.contains(KEY_RANKING_SCORE)) { mRankingScore = signals.getFloat(KEY_RANKING_SCORE); EventLogTags.writeNotificationAdjusted(getKey(), KEY_RANKING_SCORE, Float.toString(mRankingScore)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_RANKING_SCORE); } if (signals.containsKey(Adjustment.KEY_NOT_CONVERSATION)) { mIsNotConversationOverride = signals.getBoolean( Adjustment.KEY_NOT_CONVERSATION); } if (signals.containsKey(KEY_NOT_CONVERSATION) && !keysToSkip.contains(KEY_NOT_CONVERSATION)) { mIsNotConversationOverride = signals.getBoolean(KEY_NOT_CONVERSATION); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_NOT_CONVERSATION, Boolean.toString(mIsNotConversationOverride)); KEY_NOT_CONVERSATION, Boolean.toString(mIsNotConversationOverride)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_NOT_CONVERSATION); } } if (signals.containsKey(Adjustment.KEY_IMPORTANCE_PROPOSAL)) { mProposedImportance = signals.getInt(Adjustment.KEY_IMPORTANCE_PROPOSAL); if (signals.containsKey(KEY_IMPORTANCE_PROPOSAL) && !keysToSkip.contains(KEY_IMPORTANCE_PROPOSAL)) { mProposedImportance = signals.getInt(KEY_IMPORTANCE_PROPOSAL); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_IMPORTANCE_PROPOSAL, KEY_IMPORTANCE_PROPOSAL, Integer.toString(mProposedImportance)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_IMPORTANCE_PROPOSAL); } if (signals.containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) { mSensitiveContent = signals.getBoolean(Adjustment.KEY_SENSITIVE_CONTENT); } if (signals.containsKey(KEY_SENSITIVE_CONTENT) && !keysToSkip.contains(KEY_SENSITIVE_CONTENT)) { mSensitiveContent = signals.getBoolean(KEY_SENSITIVE_CONTENT); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SENSITIVE_CONTENT); } } if (android.service.notification.Flags.notificationClassification()) { if (signals.containsKey(Adjustment.KEY_TYPE)) { if (signals.containsKey(KEY_TYPE) && !keysToSkip.contains(KEY_TYPE)) { // Store original channel visibility before re-assigning channel if (!NotificationChannel.SYSTEM_RESERVED_IDS.contains(mChannel.getId())) { setOriginalChannelVisibility(mChannel.getLockscreenVisibility()); } updateNotificationChannel(signals.getParcelable(Adjustment.KEY_TYPE, updateNotificationChannel(signals.getParcelable(KEY_TYPE, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TYPE, mChannel.getId()); EventLogTags.writeNotificationAdjusted( getKey(), KEY_TYPE, mChannel.getId()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_TYPE); } } if (signals.containsKey(Adjustment.KEY_UNCLASSIFY)) { if (signals.containsKey(KEY_UNCLASSIFY) && !keysToSkip.contains(KEY_UNCLASSIFY)) { // reset original channel visibility as we're returning to the original setOriginalChannelVisibility(NotificationManager.VISIBILITY_NO_OVERRIDE); updateNotificationChannel(signals.getParcelable(Adjustment.KEY_UNCLASSIFY, updateNotificationChannel(signals.getParcelable(KEY_UNCLASSIFY, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_UNCLASSIFY, mChannel.getId()); KEY_UNCLASSIFY, mChannel.getId()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_UNCLASSIFY); } } } if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization()) && signals.containsKey(KEY_SUMMARIZATION)) { && signals.containsKey(KEY_SUMMARIZATION) && !keysToSkip.contains(KEY_SUMMARIZATION)) { CharSequence summary = signals.getCharSequence(KEY_SUMMARIZATION, signals.getString(KEY_SUMMARIZATION)); if (summary != null) { Loading @@ -842,15 +909,25 @@ public final class NotificationRecord { } EventLogTags.writeNotificationAdjusted(getKey(), KEY_SUMMARIZATION, Boolean.toString(mSummarization != null)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SUMMARIZATION); } } if (!signals.isEmpty() && adjustment.getIssuer() != null) { mAdjustmentIssuer = adjustment.getIssuer(); } if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { if (adjustment.getSignals().isEmpty()) { mAdjustments.remove(i); } // We have now gotten all the information out of the adjustments and can forget them. } } if (!com.android.server.notification.Flags.showNoisyBundledNotifications()) { // We have now gotten all the information out of the adjustments and can forget them mAdjustments.clear(); } } } String getAdjustmentIssuer() { return mAdjustmentIssuer; Loading services/core/java/com/android/server/notification/NotificationSignalExtractor.java +2 −3 Original line number Diff line number Diff line Loading @@ -20,9 +20,8 @@ import android.content.Context; import com.android.internal.compat.IPlatformCompat; /** * Extracts signals that will be useful to the {@link NotificationComparator} and caches them * on the {@link NotificationRecord} object. These annotations will * not be passed on to {@link android.service.notification.NotificationListenerService}s. * Extracts signals that will be useful to provide to notification listeners and caches them * on the {@link NotificationRecord} object. * * If you add a new Extractor be sure to add it to R.array.config_notificationSignalExtractors. */ Loading services/core/java/com/android/server/notification/RankingHelper.java +0 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.text.TextUtils.formatSimple; import android.annotation.NonNull; Loading services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -230,3 +230,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "show_noisy_bundled_notifications" namespace: "notifications" description: "If a classification arrived late and the notification made noise, show the notification as unclassified temporarily" bug: "430573835" metadata { purpose: PURPOSE_BUGFIX } } Loading
services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +87 −19 Original line number Diff line number Diff line Loading @@ -20,8 +20,14 @@ import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Flags.notificationForceGrouping; import android.content.Context; import android.util.ArraySet; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * Applies adjustments from the group helper and notification assistant */ Loading @@ -30,6 +36,14 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac private static final boolean DBG = false; private GroupHelper mGroupHelper; /** Length of time (in milliseconds) that a noisy notification will stay in its non-bundled * classification. */ @VisibleForTesting static final long HANG_TIME_MS = 30000; @VisibleForTesting InjectedTime mInjectedTimeMs = null; public void initialize(Context ctx, NotificationUsageStats usageStats) { if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); Loading @@ -43,12 +57,73 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE); final boolean removedClassification = record.hasAdjustment(KEY_UNCLASSIFY); if (Flags.showNoisyBundledNotifications() && android.service.notification.Flags.notificationClassification() && hasAdjustedClassification && record.getLastAudiblyAlertedMs() > 0) { record.applyAdjustments(new ArraySet<>(new String[] {KEY_TYPE})); return getClassificationReconsideration(record); } record.applyAdjustments(); if (notificationForceGrouping() && android.service.notification.Flags.notificationClassification()) { // Classification adjustments trigger regrouping if (mGroupHelper != null && (hasAdjustedClassification || removedClassification)) { return getRegroupReconsideration( record, hasAdjustedClassification, removedClassification); } } return null; } @Override public void setConfig(RankingConfig config) { // config is not used } @Override public void setZenHelper(ZenModeHelper helper) { } @Override public void setGroupHelper(GroupHelper groupHelper) { mGroupHelper = groupHelper; } private long getCurrentTime() { if (mInjectedTimeMs != null) { return mInjectedTimeMs.getCurrentTimeMillis(); } return System.currentTimeMillis(); } private RankingReconsideration getClassificationReconsideration(NotificationRecord record) { return new RankingReconsideration(record.getKey(), HANG_TIME_MS) { @Override public void work() { // pass } @Override public void applyChangesLocked(NotificationRecord record) { if ((getCurrentTime() - record.getLastAudiblyAlertedMs()) >= HANG_TIME_MS) { record.applyAdjustments(); getRegroupReconsideration(record, true, false).applyChangesLocked(record); } } }; } // The notification channel of the record has changed such that it's now moving to a new // UI section. We need to change the record's grouping to make sure it's not in a group // for the wrong section private RankingReconsideration getRegroupReconsideration(NotificationRecord record, boolean hasAdjustedClassification, boolean removedClassification) { return new RankingReconsideration(record.getKey(), 0) { @Override public void work() { Loading @@ -69,23 +144,16 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac } }; } } return null; } static class InjectedTime { private final long mCurrentTimeMillis; @Override public void setConfig(RankingConfig config) { // config is not used InjectedTime(long time) { mCurrentTimeMillis = time; } @Override public void setZenHelper(ZenModeHelper helper) { long getCurrentTimeMillis() { return mCurrentTimeMillis; } @Override public void setGroupHelper(GroupHelper groupHelper) { mGroupHelper = groupHelper; } }
services/core/java/com/android/server/notification/NotificationRecord.java +128 −51 Original line number Diff line number Diff line Loading @@ -21,7 +21,20 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.service.notification.Adjustment.KEY_CONTEXTUAL_ACTIONS; import static android.service.notification.Adjustment.KEY_GROUP_KEY; import static android.service.notification.Adjustment.KEY_IMPORTANCE; import static android.service.notification.Adjustment.KEY_IMPORTANCE_PROPOSAL; import static android.service.notification.Adjustment.KEY_NOT_CONVERSATION; import static android.service.notification.Adjustment.KEY_PEOPLE; import static android.service.notification.Adjustment.KEY_RANKING_SCORE; import static android.service.notification.Adjustment.KEY_SENSITIVE_CONTENT; import static android.service.notification.Adjustment.KEY_SNOOZE_CRITERIA; import static android.service.notification.Adjustment.KEY_SUMMARIZATION; import static android.service.notification.Adjustment.KEY_TEXT_REPLIES; import static android.service.notification.Adjustment.KEY_TYPE; import static android.service.notification.Adjustment.KEY_UNCLASSIFY; import static android.service.notification.Adjustment.KEY_USER_SENTIMENT; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE; Loading Loading @@ -708,6 +721,13 @@ public final class NotificationRecord { this.getSbn().getNotification()); } @VisibleForTesting int getPendingAdjustmentCount() { synchronized (mAdjustments) { return mAdjustments.size(); } } public boolean hasAdjustment(String key) { synchronized (mAdjustments) { for (Adjustment adjustment : mAdjustments) { Loading @@ -726,113 +746,160 @@ public final class NotificationRecord { } public void applyAdjustments() { long now = System.currentTimeMillis(); applyAdjustments(new ArraySet<>()); } public void applyAdjustments(@NonNull ArraySet<String> keysToSkip) { synchronized (mAdjustments) { for (Adjustment adjustment: mAdjustments) { for (int i = mAdjustments.size() - 1; i >= 0; i--) { Adjustment adjustment = mAdjustments.get(i); Bundle signals = adjustment.getSignals(); if (signals.containsKey(Adjustment.KEY_PEOPLE)) { if (signals.containsKey(KEY_PEOPLE) && !keysToSkip.contains(KEY_PEOPLE)) { final ArrayList<String> people = adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE); adjustment.getSignals().getStringArrayList(KEY_PEOPLE); setPeopleOverride(people); EventLogTags.writeNotificationAdjusted( getKey(), Adjustment.KEY_PEOPLE, people.toString()); EventLogTags.writeNotificationAdjusted(getKey(), KEY_PEOPLE, people.toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_PEOPLE); } if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) { } if (signals.containsKey(KEY_SNOOZE_CRITERIA) && !keysToSkip.contains(KEY_SNOOZE_CRITERIA)) { final ArrayList<SnoozeCriterion> snoozeCriterionList = adjustment.getSignals().getParcelableArrayList( Adjustment.KEY_SNOOZE_CRITERIA, KEY_SNOOZE_CRITERIA, android.service.notification.SnoozeCriterion.class); setSnoozeCriteria(snoozeCriterionList); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SNOOZE_CRITERIA, EventLogTags.writeNotificationAdjusted(getKey(), KEY_SNOOZE_CRITERIA, snoozeCriterionList.toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SNOOZE_CRITERIA); } } if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) { if (signals.containsKey(KEY_GROUP_KEY) && !keysToSkip.contains(KEY_GROUP_KEY)) { final String groupOverrideKey = adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY); adjustment.getSignals().getString(KEY_GROUP_KEY); setOverrideGroupKey(groupOverrideKey); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_GROUP_KEY, EventLogTags.writeNotificationAdjusted(getKey(), KEY_GROUP_KEY, groupOverrideKey); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_GROUP_KEY); } if (signals.containsKey(Adjustment.KEY_USER_SENTIMENT)) { } if (signals.containsKey(KEY_USER_SENTIMENT) && !keysToSkip.contains(KEY_USER_SENTIMENT)) { // Only allow user sentiment update from assistant if user hasn't already // expressed a preference for this channel if (!mIsAppImportanceLocked && (getChannel().getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0) { setUserSentiment(adjustment.getSignals().getInt( Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL)); KEY_USER_SENTIMENT, USER_SENTIMENT_NEUTRAL)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_USER_SENTIMENT, KEY_USER_SENTIMENT, Integer.toString(getUserSentiment())); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_USER_SENTIMENT); } } } if (signals.containsKey(Adjustment.KEY_CONTEXTUAL_ACTIONS)) { if (signals.containsKey(KEY_CONTEXTUAL_ACTIONS) && !keysToSkip.contains(KEY_CONTEXTUAL_ACTIONS)) { setSystemGeneratedSmartActions( signals.getParcelableArrayList(Adjustment.KEY_CONTEXTUAL_ACTIONS, signals.getParcelableArrayList(KEY_CONTEXTUAL_ACTIONS, android.app.Notification.Action.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_CONTEXTUAL_ACTIONS, getSystemGeneratedSmartActions().toString()); KEY_CONTEXTUAL_ACTIONS, getSystemGeneratedSmartActions().toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_CONTEXTUAL_ACTIONS); } } if (signals.containsKey(Adjustment.KEY_TEXT_REPLIES)) { setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_TEXT_REPLIES)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TEXT_REPLIES, if (signals.containsKey(KEY_TEXT_REPLIES) && !keysToSkip.contains(KEY_TEXT_REPLIES)) { setSmartReplies(signals.getCharSequenceArrayList(KEY_TEXT_REPLIES)); EventLogTags.writeNotificationAdjusted(getKey(), KEY_TEXT_REPLIES, getSmartReplies().toString()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_TEXT_REPLIES); } if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) { int importance = signals.getInt(Adjustment.KEY_IMPORTANCE); } if (signals.containsKey(KEY_IMPORTANCE) && !keysToSkip.contains(KEY_IMPORTANCE)) { int importance = signals.getInt(KEY_IMPORTANCE); importance = Math.max(IMPORTANCE_UNSPECIFIED, importance); importance = Math.min(IMPORTANCE_HIGH, importance); setAssistantImportance(importance); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_IMPORTANCE, EventLogTags.writeNotificationAdjusted(getKey(), KEY_IMPORTANCE, Integer.toString(importance)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_IMPORTANCE); } } if (signals.containsKey(Adjustment.KEY_RANKING_SCORE)) { mRankingScore = signals.getFloat(Adjustment.KEY_RANKING_SCORE); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_RANKING_SCORE, if (signals.containsKey(KEY_RANKING_SCORE) && !keysToSkip.contains(KEY_RANKING_SCORE)) { mRankingScore = signals.getFloat(KEY_RANKING_SCORE); EventLogTags.writeNotificationAdjusted(getKey(), KEY_RANKING_SCORE, Float.toString(mRankingScore)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_RANKING_SCORE); } if (signals.containsKey(Adjustment.KEY_NOT_CONVERSATION)) { mIsNotConversationOverride = signals.getBoolean( Adjustment.KEY_NOT_CONVERSATION); } if (signals.containsKey(KEY_NOT_CONVERSATION) && !keysToSkip.contains(KEY_NOT_CONVERSATION)) { mIsNotConversationOverride = signals.getBoolean(KEY_NOT_CONVERSATION); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_NOT_CONVERSATION, Boolean.toString(mIsNotConversationOverride)); KEY_NOT_CONVERSATION, Boolean.toString(mIsNotConversationOverride)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_NOT_CONVERSATION); } } if (signals.containsKey(Adjustment.KEY_IMPORTANCE_PROPOSAL)) { mProposedImportance = signals.getInt(Adjustment.KEY_IMPORTANCE_PROPOSAL); if (signals.containsKey(KEY_IMPORTANCE_PROPOSAL) && !keysToSkip.contains(KEY_IMPORTANCE_PROPOSAL)) { mProposedImportance = signals.getInt(KEY_IMPORTANCE_PROPOSAL); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_IMPORTANCE_PROPOSAL, KEY_IMPORTANCE_PROPOSAL, Integer.toString(mProposedImportance)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_IMPORTANCE_PROPOSAL); } if (signals.containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) { mSensitiveContent = signals.getBoolean(Adjustment.KEY_SENSITIVE_CONTENT); } if (signals.containsKey(KEY_SENSITIVE_CONTENT) && !keysToSkip.contains(KEY_SENSITIVE_CONTENT)) { mSensitiveContent = signals.getBoolean(KEY_SENSITIVE_CONTENT); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); KEY_SENSITIVE_CONTENT, Boolean.toString(mSensitiveContent)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SENSITIVE_CONTENT); } } if (android.service.notification.Flags.notificationClassification()) { if (signals.containsKey(Adjustment.KEY_TYPE)) { if (signals.containsKey(KEY_TYPE) && !keysToSkip.contains(KEY_TYPE)) { // Store original channel visibility before re-assigning channel if (!NotificationChannel.SYSTEM_RESERVED_IDS.contains(mChannel.getId())) { setOriginalChannelVisibility(mChannel.getLockscreenVisibility()); } updateNotificationChannel(signals.getParcelable(Adjustment.KEY_TYPE, updateNotificationChannel(signals.getParcelable(KEY_TYPE, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_TYPE, mChannel.getId()); EventLogTags.writeNotificationAdjusted( getKey(), KEY_TYPE, mChannel.getId()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_TYPE); } } if (signals.containsKey(Adjustment.KEY_UNCLASSIFY)) { if (signals.containsKey(KEY_UNCLASSIFY) && !keysToSkip.contains(KEY_UNCLASSIFY)) { // reset original channel visibility as we're returning to the original setOriginalChannelVisibility(NotificationManager.VISIBILITY_NO_OVERRIDE); updateNotificationChannel(signals.getParcelable(Adjustment.KEY_UNCLASSIFY, updateNotificationChannel(signals.getParcelable(KEY_UNCLASSIFY, NotificationChannel.class)); EventLogTags.writeNotificationAdjusted(getKey(), Adjustment.KEY_UNCLASSIFY, mChannel.getId()); KEY_UNCLASSIFY, mChannel.getId()); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_UNCLASSIFY); } } } if ((android.app.Flags.nmSummarizationUi() || android.app.Flags.nmSummarization()) && signals.containsKey(KEY_SUMMARIZATION)) { && signals.containsKey(KEY_SUMMARIZATION) && !keysToSkip.contains(KEY_SUMMARIZATION)) { CharSequence summary = signals.getCharSequence(KEY_SUMMARIZATION, signals.getString(KEY_SUMMARIZATION)); if (summary != null) { Loading @@ -842,15 +909,25 @@ public final class NotificationRecord { } EventLogTags.writeNotificationAdjusted(getKey(), KEY_SUMMARIZATION, Boolean.toString(mSummarization != null)); if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { signals.remove(KEY_SUMMARIZATION); } } if (!signals.isEmpty() && adjustment.getIssuer() != null) { mAdjustmentIssuer = adjustment.getIssuer(); } if (com.android.server.notification.Flags.showNoisyBundledNotifications()) { if (adjustment.getSignals().isEmpty()) { mAdjustments.remove(i); } // We have now gotten all the information out of the adjustments and can forget them. } } if (!com.android.server.notification.Flags.showNoisyBundledNotifications()) { // We have now gotten all the information out of the adjustments and can forget them mAdjustments.clear(); } } } String getAdjustmentIssuer() { return mAdjustmentIssuer; Loading
services/core/java/com/android/server/notification/NotificationSignalExtractor.java +2 −3 Original line number Diff line number Diff line Loading @@ -20,9 +20,8 @@ import android.content.Context; import com.android.internal.compat.IPlatformCompat; /** * Extracts signals that will be useful to the {@link NotificationComparator} and caches them * on the {@link NotificationRecord} object. These annotations will * not be passed on to {@link android.service.notification.NotificationListenerService}s. * Extracts signals that will be useful to provide to notification listeners and caches them * on the {@link NotificationRecord} object. * * If you add a new Extractor be sure to add it to R.array.config_notificationSignalExtractors. */ Loading
services/core/java/com/android/server/notification/RankingHelper.java +0 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.text.TextUtils.formatSimple; import android.annotation.NonNull; Loading
services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -230,3 +230,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "show_noisy_bundled_notifications" namespace: "notifications" description: "If a classification arrived late and the notification made noise, show the notification as unclassified temporarily" bug: "430573835" metadata { purpose: PURPOSE_BUGFIX } }