Merge "Add trace points for measuring performance"
diff --git a/Android.bp b/Android.bp
index 5250dc5..a106168 100644
--- a/Android.bp
+++ b/Android.bp
@@ -426,7 +426,7 @@
 
 java_library {
     name: "framework-annotation-proc",
-    defaults: ["framework-defaults"],
+    defaults: ["framework-aidl-export-defaults"],
     srcs: [":framework-all-sources"],
     installable: false,
     plugins: [
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 23d025f..1d0d2fb 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -251,6 +251,7 @@
         if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
             ALOGE("CountMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
+            StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
             return true;
         }
     }
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index cca793b..d7b46d1 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -491,6 +491,7 @@
             if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
                 ALOGE("DurationMetric %lld dropping data for condition dimension key %s",
                     (long long)mMetricId, newKey.getDimensionKeyInCondition().toString().c_str());
+                StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
                 return true;
             }
         }
@@ -504,6 +505,7 @@
             if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
                 ALOGE("DurationMetric %lld dropping data for what dimension key %s",
                     (long long)mMetricId, newKey.getDimensionKeyInWhat().toString().c_str());
+                StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
                 return true;
             }
         }
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 1f423cd..efd05dc 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -439,6 +439,7 @@
         if (newTupleCount > mDimensionHardLimit) {
             ALOGE("GaugeMetric %lld dropping data for dimension key %s",
                 (long long)mMetricId, newKey.toString().c_str());
+            StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
             return true;
         }
     }
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
index da1a693..8fcfe71 100644
--- a/core/java/android/content/pm/AndroidTestBaseUpdater.java
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -18,10 +18,17 @@
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
 
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.content.Context;
 import android.content.pm.PackageParser.Package;
 import android.os.Build;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
 
 /**
  * Updates a package to ensure that if it targets <= Q that the android.test.base library is
@@ -37,10 +44,26 @@
  */
 @VisibleForTesting
 public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater {
+    private static final String TAG = "AndroidTestBaseUpdater";
 
-    private static boolean apkTargetsApiLevelLessThanOrEqualToQ(Package pkg) {
-        int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
-        return targetSdkVersion <= Build.VERSION_CODES.Q;
+    /**
+     * Remove android.test.base library for apps that target SDK R or more and do not depend on
+     * android.test.runner (as it depends on classes from the android.test.base library).
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long REMOVE_ANDROID_TEST_BASE = 133396946L;
+
+    private static boolean isChangeEnabled(Package pkg) {
+        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        try {
+            return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE, pkg.applicationInfo);
+        } catch (RemoteException | NullPointerException e) {
+            Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+        }
+        // Fall back to previous behaviour.
+        return pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.Q;
     }
 
     @Override
@@ -48,7 +71,7 @@
         // Packages targeted at <= Q expect the classes in the android.test.base library
         // to be accessible so this maintains backward compatibility by adding the
         // android.test.base library to those packages.
-        if (apkTargetsApiLevelLessThanOrEqualToQ(pkg)) {
+        if (!isChangeEnabled(pkg)) {
             prefixRequiredLibrary(pkg, ANDROID_TEST_BASE);
         } else {
             // If a package already depends on android.test.runner then add a dependency on
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index fe88a91..6d60366 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2569,7 +2569,8 @@
 
         if (isItemClickable(view)) {
             addAccessibilityActionIfEnabled(info, isItemEnabled, AccessibilityAction.ACTION_CLICK);
-            info.setClickable(true);
+            // A disabled item is a separator which should not be clickable.
+            info.setClickable(isItemEnabled);
         }
 
         if (isLongClickable()) {
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 5f92cdd..a390611b 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -115,14 +115,6 @@
                 flags |= PackageManager.MATCH_INSTANT;
             }
             final List<ResolveInfo> infos = mpm.queryIntentActivities(intent, flags);
-            // Remove any activities that are not exported.
-            int totalSize = infos.size();
-            for (int j = totalSize - 1; j >= 0 ; j--) {
-                ResolveInfo info = infos.get(j);
-                if (info.activityInfo != null && !info.activityInfo.exported) {
-                    infos.remove(j);
-                }
-            }
             if (infos != null) {
                 if (resolvedComponents == null) {
                     resolvedComponents = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1e0a9f1..176676f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -152,6 +152,20 @@
     private final Runnable mStartListeningRunnable = new Runnable() {
         @Override
         public void run() {
+            if (mListening) {
+                return;
+            }
+            mListening = true;
+
+            if (mVrManager != null) {
+                try {
+                    mVrManager.registerListener(mVrStateCallbacks);
+                    mIsVrModeEnabled = mVrManager.getVrModeState();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to register VR mode state listener: ", e);
+                }
+            }
+
             mBrightnessObserver.startObserving();
             mUserTracker.startTracking();
 
@@ -167,6 +181,19 @@
     private final Runnable mStopListeningRunnable = new Runnable() {
         @Override
         public void run() {
+            if (!mListening) {
+                return;
+            }
+            mListening = false;
+
+            if (mVrManager != null) {
+                try {
+                    mVrManager.unregisterListener(mVrStateCallbacks);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
+                }
+            }
+
             mBrightnessObserver.stopObserving();
             mUserTracker.stopTracking();
 
@@ -297,39 +324,12 @@
     }
 
     public void registerCallbacks() {
-        if (mListening) {
-            return;
-        }
-
-        if (mVrManager != null) {
-            try {
-                mVrManager.registerListener(mVrStateCallbacks);
-                mIsVrModeEnabled = mVrManager.getVrModeState();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to register VR mode state listener: ", e);
-            }
-        }
-
         mBackgroundHandler.post(mStartListeningRunnable);
-        mListening = true;
     }
 
     /** Unregister all call backs, both to and from the controller */
     public void unregisterCallbacks() {
-        if (!mListening) {
-            return;
-        }
-
-        if (mVrManager != null) {
-            try {
-                mVrManager.unregisterListener(mVrStateCallbacks);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
-            }
-        }
-
         mBackgroundHandler.post(mStopListeningRunnable);
-        mListening = false;
         mControlValueInitialized = false;
     }
 
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index b1cd627..9cb8a01 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -16,9 +16,13 @@
 package com.android.server.notification;
 
 import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -37,6 +41,11 @@
     private final Callback mCallback;
     private final int mAutoGroupAtCount;
 
+    // count the number of ongoing notifications per group
+    // userId -> (package name -> (group Id -> (set of notification keys)))
+    final ArrayMap<String, ArraySet<String>>
+            mOngoingGroupCount = new ArrayMap<>();
+
     // Map of user : <Map of package : notification keys>. Only contains notifications that are not
     // grouped by the app (aka no group or sort key).
     Map<Integer, Map<String, LinkedHashSet<String>>> mUngroupedNotifications = new HashMap<>();
@@ -46,10 +55,52 @@
         mCallback = callback;
     }
 
+    private String generatePackageGroupKey(int userId, String pkg, String group) {
+        return userId + "|" + pkg + "|" + group;
+    }
+
+    @VisibleForTesting
+    protected int getOngoingGroupCount(int userId, String pkg, String group) {
+        String key = generatePackageGroupKey(userId, pkg, group);
+        return mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0)).size();
+    }
+
+    private void addToOngoingGroupCount(StatusBarNotification sbn, boolean add) {
+        if (sbn.getNotification().isGroupSummary()) return;
+        if (!sbn.isOngoing() && add) return;
+        String group = sbn.getGroup();
+        if (group == null) return;
+        int userId = sbn.getUser().getIdentifier();
+        String key = generatePackageGroupKey(userId, sbn.getPackageName(), group);
+        ArraySet<String> notifications = mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0));
+        if (add) {
+            notifications.add(sbn.getKey());
+            mOngoingGroupCount.put(key, notifications);
+        } else {
+            notifications.remove(sbn.getKey());
+            // we dont need to put it back if it is default
+        }
+        String combinedKey = generatePackageGroupKey(userId, sbn.getPackageName(), group);
+        boolean needsOngoingFlag = notifications.size() > 0;
+        mCallback.updateAutogroupSummary(sbn.getKey(), needsOngoingFlag);
+    }
+
+    public void onNotificationUpdated(StatusBarNotification childSbn,
+            boolean autogroupSummaryExists) {
+        if (childSbn.getGroup() != AUTOGROUP_KEY
+                || childSbn.getNotification().isGroupSummary()) return;
+        if (childSbn.isOngoing()) {
+            addToOngoingGroupCount(childSbn, true);
+        } else {
+            addToOngoingGroupCount(childSbn, false);
+        }
+    }
+
     public void onNotificationPosted(StatusBarNotification sbn, boolean autogroupSummaryExists) {
         if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
         try {
             List<String> notificationsToGroup = new ArrayList<>();
+            if (autogroupSummaryExists) addToOngoingGroupCount(sbn, true);
             if (!sbn.isAppGroup()) {
                 // Not grouped by the app, add to the list of notifications for the app;
                 // send grouping update if app exceeds the autogrouping limit.
@@ -90,6 +141,7 @@
 
     public void onNotificationRemoved(StatusBarNotification sbn) {
         try {
+            addToOngoingGroupCount(sbn, false);
             maybeUngroup(sbn, true, sbn.getUserId());
         } catch (Exception e) {
             Slog.e(TAG, "Error processing canceled notification", e);
@@ -159,5 +211,6 @@
         void removeAutoGroup(String key);
         void addAutoGroupSummary(int userId, String pkg, String triggeringKey);
         void removeAutoGroupSummary(int user, String pkg);
+        void updateAutogroupSummary(String key, boolean needsOngoingFlag);
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5039566..d7efa1b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -601,6 +601,40 @@
         }
     }
 
+    /**
+     * This method will update the flags of the summary.
+     * It will set it to FLAG_ONGOING_EVENT if any of its group members
+     * has the same flag. It will delete the flag otherwise
+     * @param userId user id of the autogroup summary
+     * @param pkg package of the autogroup summary
+     * @param needsOngoingFlag true if the group has at least one ongoing notification
+     */
+    @GuardedBy("mNotificationLock")
+    protected void updateAutobundledSummaryFlags(int userId, String pkg, boolean needsOngoingFlag) {
+        ArrayMap<String, String> summaries = mAutobundledSummaries.get(userId);
+        if (summaries == null) {
+            return;
+        }
+        String summaryKey = summaries.get(pkg);
+        if (summaryKey == null) {
+            return;
+        }
+        NotificationRecord summary = mNotificationsByKey.get(summaryKey);
+        if (summary == null) {
+            return;
+        }
+        int oldFlags = summary.sbn.getNotification().flags;
+        if (needsOngoingFlag) {
+            summary.sbn.getNotification().flags |= FLAG_ONGOING_EVENT;
+        } else {
+            summary.sbn.getNotification().flags &= ~FLAG_ONGOING_EVENT;
+        }
+
+        if (summary.sbn.getNotification().flags != oldFlags) {
+            mHandler.post(new EnqueueNotificationRunnable(userId, summary));
+        }
+    }
+
     private void allowDndPackage(String packageName) {
         try {
             getBinderService().setNotificationPolicyAccessGranted(packageName, true);
@@ -1917,7 +1951,6 @@
                 });
     }
 
-
     private GroupHelper getGroupHelper() {
         mAutoGroupAtCount =
                 getContext().getResources().getInteger(R.integer.config_autoGroupAtCount);
@@ -1947,6 +1980,15 @@
                     clearAutogroupSummaryLocked(userId, pkg);
                 }
             }
+
+            @Override
+            public void updateAutogroupSummary(String key, boolean needsOngoingFlag) {
+                synchronized (mNotificationLock) {
+                    NotificationRecord r = mNotificationsByKey.get(key);
+                    updateAutobundledSummaryFlags(r.getUser().getIdentifier(),
+                            r.sbn.getPackageName(), needsOngoingFlag);
+                }
+            }
         });
     }
 
@@ -5762,6 +5804,10 @@
                                             n, hasAutoGroupSummaryLocked(n));
                                 }
                             });
+                        } else if (oldSbn != null) {
+                            final NotificationRecord finalRecord = r;
+                            mHandler.post(() -> mGroupHelper.onNotificationUpdated(
+                                    finalRecord.sbn, hasAutoGroupSummaryLocked(n)));
                         }
                     } else {
                         Slog.e(TAG, "Not posting notification without small icon: " + notification);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b85009b..01ea686 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15080,19 +15080,6 @@
         return disabled;
     }
 
-    @GuardedBy("mLock")
-    private void setInstallerPackageNameLPw(PackageParser.Package pkg,
-            String installerPackageName) {
-        // Enable the parent package
-        mSettings.setInstallerPackageName(pkg.packageName, installerPackageName);
-        // Enable the child packages
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-        for (int i = 0; i < childCount; i++) {
-            PackageParser.Package childPkg = pkg.childPackages.get(i);
-            mSettings.setInstallerPackageName(childPkg.packageName, installerPackageName);
-        }
-    }
-
     private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
             int[] allUsers, PackageInstalledInfo res, UserHandle user, int installReason) {
         // Update the parent package setting
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index f652c5af..721641a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.notification;
 
+import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 
@@ -155,6 +157,196 @@
     }
 
     @Test
+    public void testAutoGroupCount_addingNoGroupSBN() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 1))
+            .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT + 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNotificationAfterChanges() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 3))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT + 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_RemoveNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        mGroupHelper.onNotificationRemoved(notifications.get(0));
+
+        verify(mCallback, times(AUTOGROUP_AT_COUNT + 2))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), AUTOGROUP_AT_COUNT);
+    }
+
+
+    @Test
+    public void testAutoGroupCount_UpdateToNoneOngoingNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        mGroupHelper.onNotificationUpdated(notifications.get(0), true);
+
+        verify(mCallback, times(1))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_AddOneOngoingNotification() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+        StatusBarNotification sbn = notifications.get(0);
+        sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+
+
+        for (StatusBarNotification current: notifications) {
+            mGroupHelper.onNotificationPosted(current, true);
+        }
+
+        verify(mCallback, times(1))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(
+                userId, pkg, AUTOGROUP_KEY), 1);
+    }
+
+    @Test
+    public void testAutoGroupCount_UpdateNoneOngoing() {
+        final String pkg = "package";
+        ArrayList<StatusBarNotification>  notifications = new ArrayList<>();
+        for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) {
+            notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM));
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            sbn.setOverrideGroupKey(AUTOGROUP_KEY);
+        }
+
+        for (StatusBarNotification sbn: notifications) {
+            mGroupHelper.onNotificationPosted(sbn, true);
+        }
+
+        verify(mCallback, times(0))
+                .updateAutogroupSummary(anyString(), eq(true));
+
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        assertEquals(mGroupHelper.getOngoingGroupCount(userId, pkg, AUTOGROUP_KEY), 0);
+    }
+
+
+    @Test
     public void testDropToZeroRemoveGroup() throws Exception {
         final String pkg = "package";
         List<StatusBarNotification> posted = new ArrayList<>();
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 2072ee5..4ea2fc0 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1182,6 +1182,36 @@
     }
 
     @Test
+    public void testAutobundledSummary_notificationAdded() {
+        NotificationRecord summary =
+                generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
+        summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
+        mService.addNotification(summary);
+        mService.mSummaryByGroupKey.put("pkg", summary);
+        mService.mAutobundledSummaries.put(0, new ArrayMap<>());
+        mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
+        mService.updateAutobundledSummaryFlags(0, "pkg", true);
+
+        assertTrue(summary.sbn.isOngoing());
+    }
+
+    @Test
+    public void testAutobundledSummary_notificationRemoved() {
+        NotificationRecord summary =
+                generateNotificationRecord(mTestNotificationChannel, 0, "pkg", true);
+        summary.getNotification().flags |= Notification.FLAG_AUTOGROUP_SUMMARY;
+        summary.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
+        mService.addNotification(summary);
+        mService.mAutobundledSummaries.put(0, new ArrayMap<>());
+        mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey());
+        mService.mSummaryByGroupKey.put("pkg", summary);
+
+        mService.updateAutobundledSummaryFlags(0, "pkg", false);
+
+        assertFalse(summary.sbn.isOngoing());
+    }
+
+    @Test
     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;