@Override
 public void onNotificationRemoved(StatusBarNotification sbn) {
   try {
     maybeUnbundle(sbn, true, sbn.getUserId());
   } catch (Exception e) {
     Slog.e(TAG, "Error processing canceled notification", e);
   }
 }
  @Override
  public void onNotificationPosted(StatusBarNotification sbn) {
    if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
    try {
      List<String> notificationsToBundle = new ArrayList<>();
      if (!sbn.isAppGroup()) {
        // Not grouped by the app, add to the list of notifications for the app;
        // send bundling update if app exceeds the autobundling limit.
        synchronized (mUnbundledNotifications) {
          Map<String, LinkedHashSet<String>> unbundledNotificationsByUser =
              mUnbundledNotifications.get(sbn.getUserId());
          if (unbundledNotificationsByUser == null) {
            unbundledNotificationsByUser = new HashMap<>();
          }
          mUnbundledNotifications.put(sbn.getUserId(), unbundledNotificationsByUser);
          LinkedHashSet<String> notificationsForPackage =
              unbundledNotificationsByUser.get(sbn.getPackageName());
          if (notificationsForPackage == null) {
            notificationsForPackage = new LinkedHashSet<>();
          }

          notificationsForPackage.add(sbn.getKey());
          unbundledNotificationsByUser.put(sbn.getPackageName(), notificationsForPackage);

          if (notificationsForPackage.size() >= AUTOBUNDLE_AT_COUNT) {
            for (String key : notificationsForPackage) {
              notificationsToBundle.add(key);
            }
          }
        }
        if (notificationsToBundle.size() > 0) {
          adjustAutobundlingSummary(
              sbn.getPackageName(), notificationsToBundle.get(0), true, sbn.getUserId());
          adjustNotificationBundling(
              sbn.getPackageName(), notificationsToBundle, true, sbn.getUserId());
        }
      } else {
        // Grouped, but not by us. Send updates to unautobundle, if we bundled it.
        maybeUnbundle(sbn, false, sbn.getUserId());
      }
    } catch (Exception e) {
      Slog.e(TAG, "Failure processing new notification", e);
    }
  }
 /**
  * Un-autobundles notifications that are now grouped by the app. Additionally cancels autobundling
  * if the status change of this notification resulted in the loose notification count being under
  * the limit.
  */
 private void maybeUnbundle(StatusBarNotification sbn, boolean notificationGone, int user) {
   List<String> notificationsToUnAutobundle = new ArrayList<>();
   boolean removeSummary = false;
   synchronized (mUnbundledNotifications) {
     Map<String, LinkedHashSet<String>> unbundledNotificationsByUser =
         mUnbundledNotifications.get(sbn.getUserId());
     if (unbundledNotificationsByUser == null || unbundledNotificationsByUser.size() == 0) {
       return;
     }
     LinkedHashSet<String> notificationsForPackage =
         unbundledNotificationsByUser.get(sbn.getPackageName());
     if (notificationsForPackage == null || notificationsForPackage.size() == 0) {
       return;
     }
     if (notificationsForPackage.remove(sbn.getKey())) {
       if (!notificationGone) {
         // Add the current notification to the unbundling list if it still exists.
         notificationsToUnAutobundle.add(sbn.getKey());
       }
       // If the status change of this notification has brought the number of loose
       // notifications back below the limit, remove the summary and un-autobundle.
       if (notificationsForPackage.size() == AUTOBUNDLE_AT_COUNT - 1) {
         removeSummary = true;
         for (String key : notificationsForPackage) {
           notificationsToUnAutobundle.add(key);
         }
       }
     }
   }
   if (notificationsToUnAutobundle.size() > 0) {
     if (removeSummary) {
       adjustAutobundlingSummary(sbn.getPackageName(), null, false, user);
     }
     adjustNotificationBundling(sbn.getPackageName(), notificationsToUnAutobundle, false, user);
   }
 }