Merge "Work on issue #77931346: The notification that should not be named appeared" into pi-dev
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 9e47ced..ba355f9 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -76,6 +76,7 @@
private static final String ATT_CONTENT_TYPE = "content_type";
private static final String ATT_SHOW_BADGE = "show_badge";
private static final String ATT_USER_LOCKED = "locked";
+ private static final String ATT_FG_SERVICE_SHOWN = "fgservice";
private static final String ATT_GROUP = "group";
private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system";
private static final String DELIMITER = ",";
@@ -144,6 +145,7 @@
// Bitwise representation of fields that have been changed by the user, preventing the app from
// making changes to these fields.
private int mUserLockedFields;
+ private boolean mFgServiceShown;
private boolean mVibrationEnabled;
private boolean mShowBadge = DEFAULT_SHOW_BADGE;
private boolean mDeleted = DEFAULT_DELETED;
@@ -200,6 +202,7 @@
mLights = in.readByte() != 0;
mVibration = in.createLongArray();
mUserLockedFields = in.readInt();
+ mFgServiceShown = in.readByte() != 0;
mVibrationEnabled = in.readByte() != 0;
mShowBadge = in.readByte() != 0;
mDeleted = in.readByte() != 0;
@@ -245,6 +248,7 @@
dest.writeByte(mLights ? (byte) 1 : (byte) 0);
dest.writeLongArray(mVibration);
dest.writeInt(mUserLockedFields);
+ dest.writeByte(mFgServiceShown ? (byte) 1 : (byte) 0);
dest.writeByte(mVibrationEnabled ? (byte) 1 : (byte) 0);
dest.writeByte(mShowBadge ? (byte) 1 : (byte) 0);
dest.writeByte(mDeleted ? (byte) 1 : (byte) 0);
@@ -281,6 +285,13 @@
/**
* @hide
*/
+ public void setFgServiceShown(boolean shown) {
+ mFgServiceShown = shown;
+ }
+
+ /**
+ * @hide
+ */
public void setDeleted(boolean deleted) {
mDeleted = deleted;
}
@@ -576,6 +587,13 @@
/**
* @hide
*/
+ public boolean isFgServiceShown() {
+ return mFgServiceShown;
+ }
+
+ /**
+ * @hide
+ */
public boolean isBlockableSystem() {
return mBlockableSystem;
}
@@ -620,6 +638,7 @@
setDeleted(safeBool(parser, ATT_DELETED, false));
setGroup(parser.getAttributeValue(null, ATT_GROUP));
lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
+ setFgServiceShown(safeBool(parser, ATT_FG_SERVICE_SHOWN, false));
setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false));
}
@@ -724,6 +743,9 @@
if (getUserLockedFields() != 0) {
out.attribute(null, ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
}
+ if (isFgServiceShown()) {
+ out.attribute(null, ATT_FG_SERVICE_SHOWN, Boolean.toString(isFgServiceShown()));
+ }
if (canShowBadge()) {
out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
}
@@ -772,6 +794,7 @@
record.put(ATT_LIGHT_COLOR, Integer.toString(getLightColor()));
record.put(ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
+ record.put(ATT_FG_SERVICE_SHOWN, Boolean.toString(isFgServiceShown()));
record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
record.put(ATT_DELETED, Boolean.toString(isDeleted()));
@@ -933,6 +956,7 @@
+ ", mLightColor=" + mLightColor
+ ", mVibration=" + Arrays.toString(mVibration)
+ ", mUserLockedFields=" + Integer.toHexString(mUserLockedFields)
+ + ", mFgServiceShown=" + mFgServiceShown
+ ", mVibrationEnabled=" + mVibrationEnabled
+ ", mShowBadge=" + mShowBadge
+ ", mDeleted=" + mDeleted
@@ -963,6 +987,7 @@
}
}
proto.write(NotificationChannelProto.USER_LOCKED_FIELDS, mUserLockedFields);
+ proto.write(NotificationChannelProto.FG_SERVICE_SHOWN, mFgServiceShown);
proto.write(NotificationChannelProto.IS_VIBRATION_ENABLED, mVibrationEnabled);
proto.write(NotificationChannelProto.SHOW_BADGE, mShowBadge);
proto.write(NotificationChannelProto.IS_DELETED, mDeleted);
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index 337aa1c..d3808e8 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -53,4 +53,5 @@
optional android.media.AudioAttributesProto audio_attributes = 16;
// If this is a blockable system notification channel.
optional bool is_blockable_system = 17;
+ optional bool fg_service_shown = 18;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b68ef11..bf17798 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4051,17 +4051,29 @@
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
r.setIsAppImportanceLocked(mRankingHelper.getIsAppImportanceLocked(pkg, callingUid));
- if ((notification.flags & FLAG_FOREGROUND_SERVICE) != 0
- && (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
- && (r.getImportance() == IMPORTANCE_MIN || r.getImportance() == IMPORTANCE_NONE)) {
- // Increase the importance of foreground service notifications unless the user had an
- // opinion otherwise
- if (TextUtils.isEmpty(channelId)
- || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
- r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
- } else {
- channel.setImportance(IMPORTANCE_LOW);
- mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
+ if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ final boolean fgServiceShown = channel.isFgServiceShown();
+ if (((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0
+ || !fgServiceShown)
+ && (r.getImportance() == IMPORTANCE_MIN
+ || r.getImportance() == IMPORTANCE_NONE)) {
+ // Increase the importance of foreground service notifications unless the user had
+ // an opinion otherwise (and the channel hasn't yet shown a fg service).
+ if (TextUtils.isEmpty(channelId)
+ || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
+ r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service");
+ } else {
+ channel.setImportance(IMPORTANCE_LOW);
+ if (!fgServiceShown) {
+ channel.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+ channel.setFgServiceShown(true);
+ }
+ mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false);
+ r.updateNotificationChannel(channel);
+ }
+ } else if (!fgServiceShown && !TextUtils.isEmpty(channelId)
+ && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
+ channel.setFgServiceShown(true);
r.updateNotificationChannel(channel);
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 58f5898..376cc64 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -557,11 +557,34 @@
assertEquals(IMPORTANCE_NONE,
mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
- final StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
+ StatusBarNotification sbn = generateNotificationRecord(channel).sbn;
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
sbn.getId(), sbn.getNotification(), sbn.getUserId());
waitForIdle();
+ // The first time a foreground service notification is shown, we allow the channel
+ // to be updated to allow it to be seen.
+ assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
+ assertEquals(IMPORTANCE_LOW,
+ mService.getNotificationRecord(sbn.getKey()).getImportance());
+ assertEquals(IMPORTANCE_LOW,
+ mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+ mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+
+ update = new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE);
+ update.setFgServiceShown(true);
+ mBinderService.updateNotificationChannelForPackage(PKG, mUid, update);
+ waitForIdle();
+ assertEquals(IMPORTANCE_NONE,
+ mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance());
+
+ sbn = generateNotificationRecord(channel).sbn;
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ waitForIdle();
+ // The second time it is shown, we keep the user's preference.
assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
assertNull(mService.getNotificationRecord(sbn.getKey()));
assertEquals(IMPORTANCE_NONE,