Loading core/java/android/app/Notification.java +3 −1 Original line number Diff line number Diff line Loading @@ -6965,8 +6965,10 @@ public class Notification implements Parcelable /** * Returns whether an app can colorize due to the android.permission.USE_COLORIZED_NOTIFICATIONS * permission. The permission is checked when a notification is enqueued. * * @hide */ private boolean hasColorizedPermission() { public boolean hasColorizedPermission() { return (flags & Notification.FLAG_CAN_COLORIZE) != 0; } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +76 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY; Loading Loading @@ -6323,6 +6324,24 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); mHandler.post(() -> { synchronized (mNotificationLock) { int count = getNotificationCount(pkg, userId); boolean removeFgsNotification = false; if (count > MAX_PACKAGE_NOTIFICATIONS) { mUsageStats.registerOverCountQuota(pkg); removeFgsNotification = true; } if (removeFgsNotification) { NotificationRecord r = findNotificationLocked(pkg, null, notificationId, userId); if (r != null) { if (DBG) { Slog.d(TAG, "Remove FGS flag not allow. Cancel FGS notification"); } removeFromNotificationListsLocked(r); cancelNotificationLocked(r, false, REASON_APP_CANCEL, true, null, SystemClock.elapsedRealtime()); } } else { // strip flag from all enqueued notifications. listeners will be informed // in post runnable. List<NotificationRecord> enqueued = findNotificationsByListLocked( Loading @@ -6340,6 +6359,7 @@ public class NotificationManagerService extends SystemService { mListeners.notifyPostedLocked(r, r); } } } }); } Loading Loading @@ -6483,9 +6503,17 @@ public class NotificationManagerService extends SystemService { checkRestrictedCategories(notification); // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE, // but it's also possible that the app has called notify() with an update to an // FGS notification that hasn't yet been displayed. Make sure we check for any // FGS-related situation up front, outside of any locks so it's safe to call into // the Activity Manager. final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification( notification, tag, id, pkg, userId); // Fix the notification as best we can. try { fixNotification(notification, pkg, tag, id, userId); fixNotification(notification, pkg, tag, id, userId, notificationUid, policy); } catch (Exception e) { if (notification.isForegroundService()) { throw new SecurityException("Invalid FGS notification", e); Loading @@ -6494,13 +6522,7 @@ public class NotificationManagerService extends SystemService { return; } // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE, // but it's also possible that the app has called notify() with an update to an // FGS notification that hasn't yet been displayed. Make sure we check for any // FGS-related situation up front, outside of any locks so it's safe to call into // the Activity Manager. final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification( notification, tag, id, pkg, userId); if (policy == ServiceNotificationPolicy.UPDATE_ONLY) { // Proceed if the notification is already showing/known, otherwise ignore // because the service lifecycle logic has retained responsibility for its Loading Loading @@ -6663,14 +6685,20 @@ public class NotificationManagerService extends SystemService { @VisibleForTesting protected void fixNotification(Notification notification, String pkg, String tag, int id, int userId) throws NameNotFoundException, RemoteException { @UserIdInt int userId, int notificationUid, ServiceNotificationPolicy fgsPolicy) throws NameNotFoundException, RemoteException { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Notification.addFieldsFromContext(ai, notification); int canColorize = mPackageManagerClient.checkPermission( android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg); if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) { notification.flags &= ~FLAG_FOREGROUND_SERVICE; } int canColorize = getContext().checkPermission( android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, -1, notificationUid); if (canColorize == PERMISSION_GRANTED) { notification.flags |= Notification.FLAG_CAN_COLORIZE; } else { Loading Loading @@ -7059,6 +7087,29 @@ public class NotificationManagerService extends SystemService { return mPermissionHelper.hasPermission(uid); } private int getNotificationCount(String pkg, int userId) { int count = 0; synchronized (mNotificationLock) { final int numListSize = mNotificationList.size(); for (int i = 0; i < numListSize; i++) { final NotificationRecord existing = mNotificationList.get(i); if (existing.getSbn().getPackageName().equals(pkg) && existing.getSbn().getUserId() == userId) { count++; } } final int numEnqSize = mEnqueuedNotifications.size(); for (int i = 0; i < numEnqSize; i++) { final NotificationRecord existing = mEnqueuedNotifications.get(i); if (existing.getSbn().getPackageName().equals(pkg) && existing.getSbn().getUserId() == userId) { count++; } } } return count; } protected int getNotificationCount(String pkg, int userId, int excludedId, String excludedTag) { int count = 0; Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +177 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/app/Notification.java +3 −1 Original line number Diff line number Diff line Loading @@ -6965,8 +6965,10 @@ public class Notification implements Parcelable /** * Returns whether an app can colorize due to the android.permission.USE_COLORIZED_NOTIFICATIONS * permission. The permission is checked when a notification is enqueued. * * @hide */ private boolean hasColorizedPermission() { public boolean hasColorizedPermission() { return (flags & Notification.FLAG_CAN_COLORIZE) != 0; } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +76 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY; Loading Loading @@ -6323,6 +6324,24 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); mHandler.post(() -> { synchronized (mNotificationLock) { int count = getNotificationCount(pkg, userId); boolean removeFgsNotification = false; if (count > MAX_PACKAGE_NOTIFICATIONS) { mUsageStats.registerOverCountQuota(pkg); removeFgsNotification = true; } if (removeFgsNotification) { NotificationRecord r = findNotificationLocked(pkg, null, notificationId, userId); if (r != null) { if (DBG) { Slog.d(TAG, "Remove FGS flag not allow. Cancel FGS notification"); } removeFromNotificationListsLocked(r); cancelNotificationLocked(r, false, REASON_APP_CANCEL, true, null, SystemClock.elapsedRealtime()); } } else { // strip flag from all enqueued notifications. listeners will be informed // in post runnable. List<NotificationRecord> enqueued = findNotificationsByListLocked( Loading @@ -6340,6 +6359,7 @@ public class NotificationManagerService extends SystemService { mListeners.notifyPostedLocked(r, r); } } } }); } Loading Loading @@ -6483,9 +6503,17 @@ public class NotificationManagerService extends SystemService { checkRestrictedCategories(notification); // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE, // but it's also possible that the app has called notify() with an update to an // FGS notification that hasn't yet been displayed. Make sure we check for any // FGS-related situation up front, outside of any locks so it's safe to call into // the Activity Manager. final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification( notification, tag, id, pkg, userId); // Fix the notification as best we can. try { fixNotification(notification, pkg, tag, id, userId); fixNotification(notification, pkg, tag, id, userId, notificationUid, policy); } catch (Exception e) { if (notification.isForegroundService()) { throw new SecurityException("Invalid FGS notification", e); Loading @@ -6494,13 +6522,7 @@ public class NotificationManagerService extends SystemService { return; } // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE, // but it's also possible that the app has called notify() with an update to an // FGS notification that hasn't yet been displayed. Make sure we check for any // FGS-related situation up front, outside of any locks so it's safe to call into // the Activity Manager. final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification( notification, tag, id, pkg, userId); if (policy == ServiceNotificationPolicy.UPDATE_ONLY) { // Proceed if the notification is already showing/known, otherwise ignore // because the service lifecycle logic has retained responsibility for its Loading Loading @@ -6663,14 +6685,20 @@ public class NotificationManagerService extends SystemService { @VisibleForTesting protected void fixNotification(Notification notification, String pkg, String tag, int id, int userId) throws NameNotFoundException, RemoteException { @UserIdInt int userId, int notificationUid, ServiceNotificationPolicy fgsPolicy) throws NameNotFoundException, RemoteException { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Notification.addFieldsFromContext(ai, notification); int canColorize = mPackageManagerClient.checkPermission( android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg); if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) { notification.flags &= ~FLAG_FOREGROUND_SERVICE; } int canColorize = getContext().checkPermission( android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, -1, notificationUid); if (canColorize == PERMISSION_GRANTED) { notification.flags |= Notification.FLAG_CAN_COLORIZE; } else { Loading Loading @@ -7059,6 +7087,29 @@ public class NotificationManagerService extends SystemService { return mPermissionHelper.hasPermission(uid); } private int getNotificationCount(String pkg, int userId) { int count = 0; synchronized (mNotificationLock) { final int numListSize = mNotificationList.size(); for (int i = 0; i < numListSize; i++) { final NotificationRecord existing = mNotificationList.get(i); if (existing.getSbn().getPackageName().equals(pkg) && existing.getSbn().getUserId() == userId) { count++; } } final int numEnqSize = mEnqueuedNotifications.size(); for (int i = 0; i < numEnqSize; i++) { final NotificationRecord existing = mEnqueuedNotifications.get(i); if (existing.getSbn().getPackageName().equals(pkg) && existing.getSbn().getUserId() == userId) { count++; } } } return count; } protected int getNotificationCount(String pkg, int userId, int excludedId, String excludedTag) { int count = 0; Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +177 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes