Merge "Clear notifications deletes configs"
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 64477a5..aed2927 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -38,6 +38,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.notification.NotificationManagerService.DumpFilter;
 
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -81,6 +84,39 @@
     }
 
     @Override
+    protected ArrayMap<Boolean, ArrayList<ComponentName>>
+            resetComponents(String packageName, int userId) {
+        resetPackage(packageName, userId);
+        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
+        changes.put(true, new ArrayList<>(0));
+        changes.put(false, new ArrayList<>(0));
+        return changes;
+    }
+
+    /**
+     *  @return true if the passed package is enabled. false otherwise
+     */
+    boolean resetPackage(String packageName, int userId) {
+        boolean isAllowed = super.isPackageOrComponentAllowed(packageName, userId);
+        boolean isDefault = super.isDefaultComponentOrPackage(packageName);
+        if (!isAllowed && isDefault) {
+            setPackageOrComponentEnabled(packageName, userId, true, true);
+        }
+        if (isAllowed && !isDefault) {
+            setPackageOrComponentEnabled(packageName, userId, true, false);
+        }
+        return !isAllowed && isDefault;
+    }
+
+    @Override
+    void writeDefaults(XmlSerializer out) throws IOException {
+        synchronized (mDefaultsLock) {
+            String defaults = String.join(ENABLED_SERVICES_SEPARATOR, mDefaultPackages);
+            out.attribute(null, ATT_DEFAULTS, defaults);
+        }
+    }
+
+    @Override
     protected Config getConfig() {
         final Config c = new Config();
         c.caption = "condition provider";
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 4828bbf..48b0fd6 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -105,6 +105,7 @@
     static final String ATT_USER_ID = "user";
     static final String ATT_IS_PRIMARY = "primary";
     static final String ATT_VERSION = "version";
+    static final String ATT_DEFAULTS = "defaults";
 
     static final int DB_VERSION = 1;
 
@@ -128,6 +129,10 @@
      */
     private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
     private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
+    // we need these packages to be protected because classes that inherit from it need to see it
+    protected final Object mDefaultsLock = new Object();
+    protected final ArraySet<ComponentName> mDefaultComponents = new ArraySet<>();
+    protected final ArraySet<String> mDefaultPackages = new ArraySet<>();
 
     // lists the component names of all enabled (and therefore potentially connected)
     // app services for current profiles.
@@ -179,6 +184,112 @@
         }
     }
 
+    protected void addDefaultComponentOrPackage(String packageOrComponent) {
+        if (packageOrComponent != null) {
+            synchronized (mDefaultsLock) {
+                ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
+                if (cn == null) {
+                    mDefaultPackages.add(packageOrComponent);
+                } else {
+                    mDefaultPackages.add(cn.getPackageName());
+                    mDefaultComponents.add(cn);
+                }
+            }
+        }
+    }
+
+    boolean isDefaultComponentOrPackage(String packageOrComponent) {
+        synchronized (mDefaultsLock) {
+            ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
+            if (cn == null) {
+                return mDefaultPackages.contains(packageOrComponent);
+            } else {
+                return mDefaultComponents.contains(cn);
+            }
+        }
+    }
+
+    ArraySet<ComponentName> getDefaultComponents() {
+        synchronized (mDefaultsLock) {
+            return new ArraySet<>(mDefaultComponents);
+        }
+    }
+
+    ArraySet<String> getDefaultPackages() {
+        synchronized (mDefaultsLock) {
+            return new ArraySet<>(mDefaultPackages);
+        }
+    }
+
+    /**
+     * When resetting a package, we need to enable default components that belong to that packages
+     * we also need to disable components that are not default to return the managed service state
+     * to when a new android device is first turned on for that package.
+     *
+     * @param packageName package to reset.
+     * @param userId the android user id
+     * @return a list of components that were permitted
+     */
+    @NonNull
+    ArrayMap<Boolean, ArrayList<ComponentName>> resetComponents(String packageName, int userId) {
+        // components that we want to enable
+        ArrayList<ComponentName> componentsToEnable =
+                new ArrayList<>(mDefaultComponents.size());
+
+        // components that were removed
+        ArrayList<ComponentName> disabledComponents =
+                new ArrayList<>(mDefaultComponents.size());
+
+        // all components that are enabled now
+        ArraySet<ComponentName> enabledComponents =
+                new ArraySet<>(getAllowedComponents(userId));
+
+        boolean changed = false;
+
+        synchronized (mDefaultsLock) {
+            // record all components that are enabled but should not be by default
+            for (int i = 0; i < mDefaultComponents.size() && enabledComponents.size() > 0; i++) {
+                ComponentName currentDefault = mDefaultComponents.valueAt(i);
+                if (packageName.equals(currentDefault.getPackageName())
+                        && !enabledComponents.contains(currentDefault)) {
+                    componentsToEnable.add(currentDefault);
+                }
+            }
+            synchronized (mApproved) {
+                final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
+                        userId);
+                if (approvedByType != null) {
+                    final int M = approvedByType.size();
+                    for (int j = 0; j < M; j++) {
+                        final ArraySet<String> approved = approvedByType.valueAt(j);
+                        for (int i = 0; i < enabledComponents.size(); i++) {
+                            ComponentName currentComponent = enabledComponents.valueAt(i);
+                            if (packageName.equals(currentComponent.getPackageName())
+                                    && !mDefaultComponents.contains(currentComponent)) {
+                                if (approved.remove(currentComponent.flattenToString())) {
+                                    disabledComponents.add(currentComponent);
+                                    changed = true;
+                                }
+                            }
+                        }
+                        for (int i = 0; i < componentsToEnable.size(); i++) {
+                            ComponentName candidate = componentsToEnable.get(i);
+                            changed |= approved.add(candidate.flattenToString());
+                        }
+                    }
+
+                }
+            }
+        }
+        if (changed) rebindServices(false, USER_ALL);
+
+        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
+        changes.put(true, componentsToEnable);
+        changes.put(false, disabledComponents);
+
+        return changes;
+    }
+
     protected int getBindFlags() {
         return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
     }
@@ -310,11 +421,24 @@
         }
     }
 
+    void writeDefaults(XmlSerializer out) throws IOException {
+        synchronized (mDefaultsLock) {
+            List<String> componentStrings = new ArrayList<>(mDefaultComponents.size());
+            for (int i = 0; i < mDefaultComponents.size(); i++) {
+                componentStrings.add(mDefaultComponents.valueAt(i).flattenToString());
+            }
+            String defaults = String.join(ENABLED_SERVICES_SEPARATOR, componentStrings);
+            out.attribute(null, ATT_DEFAULTS, defaults);
+        }
+    }
+
     public void writeXml(XmlSerializer out, boolean forBackup, int userId) throws IOException {
         out.startTag(null, getConfig().xmlTag);
 
         out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));
 
+        writeDefaults(out);
+
         if (forBackup) {
             trimApprovedListsAccordingToInstalledServices(userId);
         }
@@ -378,6 +502,27 @@
         loadAllowedComponentsFromSettings();
     }
 
+    void readDefaults(XmlPullParser parser) {
+        String defaultComponents = XmlUtils.readStringAttribute(parser, ATT_DEFAULTS);
+        if (defaultComponents == null) {
+            return;
+        }
+        String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR);
+        synchronized (mDefaultsLock) {
+            for (int i = 0; i < components.length; i++) {
+                if (!TextUtils.isEmpty(components[i])) {
+                    ComponentName cn = ComponentName.unflattenFromString(components[i]);
+                    if (cn != null) {
+                        mDefaultPackages.add(cn.getPackageName());
+                        mDefaultComponents.add(cn);
+                    } else {
+                        mDefaultPackages.add(components[i]);
+                    }
+                }
+            }
+        }
+    }
+
     public void readXml(
             XmlPullParser parser,
             TriPredicate<String, Integer, String> allowedManagedServicePackages,
@@ -386,6 +531,7 @@
             throws XmlPullParserException, IOException {
         // read grants
         int type;
+        readDefaults(parser);
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
             String tag = parser.getName();
             if (type == XmlPullParser.END_TAG
@@ -785,9 +931,9 @@
         return queryPackageForServices(packageName, 0, userId);
     }
 
-    protected Set<ComponentName> queryPackageForServices(String packageName, int extraFlags,
+    protected ArraySet<ComponentName> queryPackageForServices(String packageName, int extraFlags,
             int userId) {
-        Set<ComponentName> installed = new ArraySet<>();
+        ArraySet<ComponentName> installed = new ArraySet<>();
         final PackageManager pm = mContext.getPackageManager();
         Intent queryIntent = new Intent(mConfig.serviceInterface);
         if (!TextUtils.isEmpty(packageName)) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3d9e635c..2d4c6cf 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -356,7 +356,6 @@
     private static final int REQUEST_CODE_TIMEOUT = 1;
     private static final String SCHEME_TIMEOUT = "timeout";
     private static final String EXTRA_KEY = "key";
-
     private IActivityManager mAm;
     private ActivityManager mActivityManager;
     private IPackageManager mPackageManager;
@@ -524,24 +523,21 @@
 
     }
 
-    protected void readDefaultApprovedServices(int userId) {
+
+    void loadDefaultApprovedServices(int userId) {
         String defaultListenerAccess = getContext().getResources().getString(
                 com.android.internal.R.string.config_defaultListenerAccessPackages);
         if (defaultListenerAccess != null) {
-            for (String whitelisted :
-                    defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)) {
-                // Gather all notification listener components for candidate pkgs.
-                Set<ComponentName> approvedListeners =
-                        mListeners.queryPackageForServices(whitelisted,
+            String[] listeners =
+                    defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
+            for (int i = 0; i < listeners.length; i++) {
+                ArraySet<ComponentName> approvedListeners =
+                        mListeners.queryPackageForServices(listeners[i],
                                 MATCH_DIRECT_BOOT_AWARE
                                         | MATCH_DIRECT_BOOT_UNAWARE, userId);
-                for (ComponentName cn : approvedListeners) {
-                    try {
-                        getBinderService().setNotificationListenerAccessGrantedForUser(cn,
-                                    userId, true);
-                    } catch (RemoteException e) {
-                        e.printStackTrace();
-                    }
+                for (int k = 0; k < approvedListeners.size(); k++) {
+                    ComponentName cn = approvedListeners.valueAt(k);
+                    mListeners.addDefaultComponentOrPackage(cn.flattenToString());
                 }
             }
         }
@@ -549,46 +545,86 @@
         String defaultDndAccess = getContext().getResources().getString(
                 com.android.internal.R.string.config_defaultDndAccessPackages);
         if (defaultDndAccess != null) {
-            for (String whitelisted :
-                    defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)) {
-                try {
-                    getBinderService().setNotificationPolicyAccessGranted(whitelisted, true);
-                } catch (RemoteException e) {
-                    e.printStackTrace();
-                }
+            String[] dnds = defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
+            for (int i = 0; i < dnds.length; i++) {
+                mConditionProviders.addDefaultComponentOrPackage(dnds[i]);
             }
         }
 
+
+        ArraySet<String> assistants = new ArraySet<>();
+        String deviceAssistant = DeviceConfig.getProperty(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
+        if (deviceAssistant != null) {
+            assistants.addAll(Arrays.asList(deviceAssistant.split(
+                    ManagedServices.ENABLED_SERVICES_SEPARATOR)));
+        }
+        assistants.addAll(Arrays.asList(getContext().getResources().getString(
+                com.android.internal.R.string.config_defaultAssistantAccessComponent)
+                .split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
+        for (int i = 0; i < assistants.size(); i++) {
+            String cnString = assistants.valueAt(i);
+            mAssistants.addDefaultComponentOrPackage(cnString);
+        }
+    }
+
+    protected void allowDefaultApprovedServices(int userId) {
+
+        ArraySet<ComponentName> defaultListeners = mListeners.getDefaultComponents();
+        for (int i = 0; i < defaultListeners.size(); i++) {
+            ComponentName cn = defaultListeners.valueAt(i);
+            allowNotificationListener(userId, cn);
+        }
+
+        ArraySet<String> defaultDnds = mConditionProviders.getDefaultPackages();
+        for (int i = 0; i < defaultDnds.size(); i++) {
+            allowDndPackage(defaultDnds.valueAt(i));
+        }
+
         setDefaultAssistantForUser(userId);
     }
 
     protected void setDefaultAssistantForUser(int userId) {
-        List<ComponentName> validAssistants = new ArrayList<>(
-                mAssistants.queryPackageForServices(
-                        null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId));
-
-        List<String> candidateStrs = new ArrayList<>();
-        candidateStrs.add(DeviceConfig.getProperty(
-                DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE));
-        candidateStrs.add(getContext().getResources().getString(
-                com.android.internal.R.string.config_defaultAssistantAccessComponent));
-
-        for (String candidateStr : candidateStrs) {
-            if (TextUtils.isEmpty(candidateStr)) {
-                continue;
-            }
-            ComponentName candidate = ComponentName.unflattenFromString(candidateStr);
-            if (candidate != null && validAssistants.contains(candidate)) {
-                setNotificationAssistantAccessGrantedForUserInternal(candidate, userId, true);
-                Slog.d(TAG, String.format("Set default NAS to be %s in %d", candidateStr, userId));
-                return;
-            } else {
-                Slog.w(TAG, "Invalid default NAS config is found: " + candidateStr);
-            }
+        ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
+        // We should have only one default assistant by default
+        // allowAssistant should execute once in practice
+        for (int i = 0; i < defaults.size(); i++) {
+            ComponentName cn = defaults.valueAt(i);
+            if (allowAssistant(userId, cn)) return;
         }
     }
 
+    private void allowDndPackage(String packageName) {
+        try {
+            getBinderService().setNotificationPolicyAccessGranted(packageName, true);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void allowNotificationListener(int userId, ComponentName cn) {
+
+        try {
+            getBinderService().setNotificationListenerAccessGrantedForUser(cn,
+                        userId, true);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private boolean allowAssistant(int userId, ComponentName candidate) {
+        Set<ComponentName> validAssistants =
+                mAssistants.queryPackageForServices(
+                        null,
+                        MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
+        if (candidate != null && validAssistants.contains(candidate)) {
+            setNotificationAssistantAccessGrantedForUserInternal(candidate, userId, true);
+            return true;
+        }
+        return false;
+    }
+
     void readPolicyXml(InputStream stream, boolean forRestore, int userId)
             throws XmlPullParserException, NumberFormatException, IOException {
         final XmlPullParser parser = Xml.newPullParser();
@@ -656,7 +692,8 @@
             } catch (FileNotFoundException e) {
                 // No data yet
                 // Load default managed services approvals
-                readDefaultApprovedServices(USER_SYSTEM);
+                loadDefaultApprovedServices(USER_SYSTEM);
+                allowDefaultApprovedServices(USER_SYSTEM);
             } catch (IOException e) {
                 Log.wtf(TAG, "Unable to read notification policy", e);
             } catch (NumberFormatException e) {
@@ -1363,7 +1400,7 @@
                 if (userId != USER_NULL) {
                     mUserProfiles.updateCache(context);
                     if (!mUserProfiles.isManagedProfile(userId)) {
-                        readDefaultApprovedServices(userId);
+                        allowDefaultApprovedServices(userId);
                     }
                 }
             } else if (action.equals(Intent.ACTION_USER_REMOVED)) {
@@ -1741,7 +1778,6 @@
 
         mPolicyFile = policyFile;
         loadPolicyFile();
-
         mStatusBar = getLocalService(StatusBarManagerInternal.class);
         if (mStatusBar != null) {
             mStatusBar.setNotificationDelegate(mNotificationDelegate);
@@ -2957,21 +2993,52 @@
 
         @Override
         public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException {
+            boolean packagesChanged = false;
             checkCallerIsSystem();
-
             // Cancel posted notifications
+            final int userId = UserHandle.getUserId(uid);
             cancelAllNotificationsInt(MY_UID, MY_PID, packageName, null, 0, 0, true,
                     UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
 
-            final String[] packages = new String[] {packageName};
-            final int[] uids = new int[] {uid};
-
-            // Listener & assistant
-            mListeners.onPackagesChanged(true, packages, uids);
-            mAssistants.onPackagesChanged(true, packages, uids);
-
             // Zen
-            mConditionProviders.onPackagesChanged(true, packages, uids);
+            packagesChanged |=
+                    mConditionProviders.resetPackage(packageName, userId);
+
+            // Listener
+            ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
+                    mListeners.resetComponents(packageName, userId);
+            packagesChanged |= changedListeners.get(true).size() > 0
+                    || changedListeners.get(false).size() > 0;
+
+            // When a listener is enabled, we enable the dnd package as a secondary
+            for (int i = 0; i < changedListeners.get(true).size(); i++) {
+                mConditionProviders.setPackageOrComponentEnabled(
+                        changedListeners.get(true).get(i).getPackageName(),
+                        userId, false, true);
+            }
+
+            // Assistant
+            ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
+                    mAssistants.resetComponents(packageName, userId);
+            packagesChanged |= changedAssistants.get(true).size() > 0
+                    || changedAssistants.get(false).size() > 0;
+
+            // we want only one assistant enabled
+            for (int i = 1; i < changedAssistants.get(true).size(); i++) {
+                mAssistants.setPackageOrComponentEnabled(
+                        changedAssistants.get(true).get(i).flattenToString(),
+                        userId, true, false);
+            }
+
+            // When the default assistant is enabled, we enable the dnd package as a secondary
+            if (changedAssistants.get(true).size() > 0) {
+                //we want only one assistant active
+                mConditionProviders
+                        .setPackageOrComponentEnabled(
+                                changedAssistants.get(true).get(0).getPackageName(),
+                                userId, false, true);
+
+            }
 
             // Snoozing
             mSnoozeHelper.clearData(UserHandle.getUserId(uid), packageName);
@@ -2981,6 +3048,14 @@
                 mPreferencesHelper.clearData(packageName, uid);
             }
 
+            if (packagesChanged) {
+                getContext().sendBroadcastAsUser(new Intent(
+                                ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
+                                .setPackage(packageName)
+                                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT),
+                        UserHandle.of(userId), null);
+            }
+
             handleSavePolicyFile();
         }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 8aaf29a..7b7470c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -27,7 +27,6 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -58,13 +57,13 @@
 import android.util.Xml;
 
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
 import com.android.server.UiServiceTestCase;
 
 import com.google.android.collect.Lists;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -76,6 +75,7 @@
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -331,6 +331,147 @@
         }
     }
 
+    /** Test that restore ignores the user id attribute and applies the data to the target user. */
+    @Test
+    public void testWriteReadXml_writeReadDefaults() throws Exception {
+        // setup
+        ManagedServices service1 =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        ManagedServices service2 =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        XmlSerializer serializer = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        BufferedOutputStream outStream = new BufferedOutputStream(baos);
+        serializer.setOutput(outStream, "utf-8");
+
+        //data setup
+        service1.addDefaultComponentOrPackage("package/class");
+        serializer.startDocument(null, true);
+        service1.writeXml(serializer, false, 0);
+        serializer.endDocument();
+        outStream.flush();
+
+        final XmlPullParser parser = Xml.newPullParser();
+        BufferedInputStream input = new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray()));
+
+        parser.setInput(input, StandardCharsets.UTF_8.name());
+        XmlUtils.beginDocument(parser, "test");
+        service2.readXml(parser, null, false, 0);
+        ArraySet<ComponentName> defaults = service2.getDefaultComponents();
+
+        assertEquals(1, defaults.size());
+        assertEquals(new ComponentName("package", "class"), defaults.valueAt(0));
+
+    }
+
+    @Test
+    public void resetPackage_enableDefaultsOnly() {
+        // setup
+        ManagedServices service =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                0, true);
+        service.addDefaultComponentOrPackage("package/default");
+        service.addDefaultComponentOrPackage("package2/default");
+
+        ArrayMap<Boolean, ArrayList<ComponentName>> componentsToActivate =
+                service.resetComponents("package", 0);
+
+        assertEquals(1, componentsToActivate.get(true).size());
+        assertEquals(new ComponentName("package", "default"),
+                componentsToActivate.get(true).get(0));
+    }
+
+
+    @Test
+    public void resetPackage_nonDefaultsRemoved() {
+        // setup
+        ManagedServices service =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                0, true);
+        service.addDefaultComponentOrPackage("package/default");
+        service.addDefaultComponentOrPackage("package2/default");
+
+        ArrayMap<Boolean, ArrayList<ComponentName>> componentsToActivate =
+                service.resetComponents("package", 0);
+
+        assertEquals(1, componentsToActivate.get(true).size());
+        assertEquals(new ComponentName("package", "not-default"),
+                componentsToActivate.get(false).get(0));
+    }
+
+    @Test
+    public void resetPackage_onlyDefaultsOnly() {
+        // setup
+        ManagedServices service =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                0, true);
+        service.addDefaultComponentOrPackage("package/default");
+        service.addDefaultComponentOrPackage("package2/default");
+
+        assertEquals(3, service.getAllowedComponents(0).size());
+
+        service.resetComponents("package", 0);
+
+        List<ComponentName> components =  service.getAllowedComponents(0);
+        assertEquals(3, components.size());
+        assertTrue(components.contains(new ComponentName("package", "default")));
+    }
+
+    @Test
+    public void resetPackage_affectCurrentUserOnly() {
+        // setup
+        ManagedServices service =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                0, true);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                1, true);
+        service.addDefaultComponentOrPackage("package/default");
+        service.addDefaultComponentOrPackage("package2/default");
+
+        service.resetComponents("package", 0);
+
+        List<ComponentName> components =  service.getAllowedComponents(1);
+        assertEquals(3, components.size());
+    }
+
+    @Test
+    public void resetPackage_samePackageMultipleClasses() {
+        // setup
+        ManagedServices service =
+                new TestManagedServices(
+                        getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT);
+        service.addApprovedList(
+                "package/not-default:another-package/not-default:package2/default",
+                0, true);
+        service.addApprovedList(
+                "package/class:another-package/class:package2/class",
+                0, true);
+        service.addDefaultComponentOrPackage("package/default");
+        service.addDefaultComponentOrPackage("package2/default");
+
+        service.resetComponents("package", 0);
+
+        List<ComponentName> components =  service.getAllowedComponents(0);
+        assertEquals(5, components.size());
+        assertTrue(components.contains(new ComponentName("package", "default")));
+    }
+
     /** Test that backup only writes packages/components that belong to the target user. */
     @Test
     public void testWriteXml_onlyBackupsForTargetUser() throws Exception {
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 fdd1a59..2de8d05 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -379,6 +379,15 @@
         // Setup managed services
         mListener = mListeners.new ManagedServiceInfo(
                 null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
+        ComponentName defaultComponent = ComponentName.unflattenFromString("config/device");
+        ArraySet<ComponentName> components = new ArraySet<>();
+        components.add(defaultComponent);
+        when(mListeners.getDefaultComponents()).thenReturn(components);
+        when(mConditionProviders.getDefaultPackages())
+                .thenReturn(new ArraySet<>(Arrays.asList("config")));
+        when(mAssistants.getDefaultComponents()).thenReturn(components);
+        when(mAssistants.queryPackageForServices(
+                anyString(), anyInt(), anyInt())).thenReturn(components);
         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
         ManagedServices.Config listenerConfig = new ManagedServices.Config();
         listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS;
@@ -422,6 +431,12 @@
                 .getUiAutomation().dropShellPermissionIdentity();
     }
 
+    private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
+        ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
+        changed.put(true, new ArrayList<>());
+        changed.put(false, new ArrayList<>());
+        return changed;
+    }
     private ApplicationInfo getApplicationInfo(String pkg, int uid) {
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.uid = uid;
@@ -3289,6 +3304,8 @@
     @Test
     public void testBackup() throws Exception {
         int systemChecks = mService.countSystemChecks;
+        when(mListeners.queryPackageForServices(anyString(), anyInt(), anyInt()))
+                .thenReturn(new ArraySet<>());
         mBinderService.getBackupPayload(1);
         assertEquals(1, mService.countSystemChecks - systemChecks);
     }
@@ -4482,16 +4499,20 @@
     public void setDefaultAssistantForUser_fromConfigXml() {
         clearDeviceConfig();
         ComponentName xmlConfig = new ComponentName("config", "xml");
+        ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
         when(mResources
                 .getString(
                         com.android.internal.R.string.config_defaultAssistantAccessComponent))
                 .thenReturn(xmlConfig.flattenToString());
         when(mContext.getResources()).thenReturn(mResources);
-        when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
-                .thenReturn(Collections.singleton(xmlConfig));
+        when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
+                .thenReturn(components);
+        when(mAssistants.getDefaultComponents())
+                .thenReturn(components);
         mService.setNotificationAssistantAccessGrantedCallback(
                 mNotificationAssistantAccessGrantedCallback);
 
+
         mService.setDefaultAssistantForUser(0);
 
         verify(mNotificationAssistantAccessGrantedCallback)
@@ -4507,8 +4528,10 @@
                 .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
                 .thenReturn(xmlConfig.flattenToString());
         when(mContext.getResources()).thenReturn(mResources);
-        when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
+        when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
                 .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
+        when(mAssistants.getDefaultComponents())
+                .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
         mService.setNotificationAssistantAccessGrantedCallback(
                 mNotificationAssistantAccessGrantedCallback);
 
@@ -4529,7 +4552,9 @@
         when(mContext.getResources()).thenReturn(mResources);
         // Only xmlConfig is valid, deviceConfig is not.
         when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
-                .thenReturn(Collections.singleton(xmlConfig));
+                .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
+        when(mAssistants.getDefaultComponents())
+                .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
         mService.setNotificationAssistantAccessGrantedCallback(
                 mNotificationAssistantAccessGrantedCallback);
 
@@ -4540,6 +4565,53 @@
     }
 
     @Test
+    public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
+        ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
+                generateResetComponentValues();
+        when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
+        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
+        ComponentName deviceConfig1 = new ComponentName("device", "config1");
+        ComponentName deviceConfig2 = new ComponentName("device", "config2");
+        changes.put(true, new ArrayList(Arrays.asList(deviceConfig1, deviceConfig2)));
+        changes.put(false, new ArrayList());
+        when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
+        mService.getBinderService().clearData("device", 0, false);
+        verify(mAssistants, times(1))
+                .setPackageOrComponentEnabled(
+                        eq("device/config2"),
+                        eq(0), eq(true), eq(false));
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                eq("device"), eq(0), eq(false), eq(true));
+    }
+
+    @Test
+    public void clearDefaultListenersPackageShouldEnableIt() throws RemoteException {
+        ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
+                generateResetComponentValues();
+        when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changedAssistants);
+        ComponentName deviceConfig = new ComponentName("device", "config");
+        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
+        changes.put(true, new ArrayList(Arrays.asList(deviceConfig)));
+        changes.put(false, new ArrayList());
+        when(mListeners.resetComponents(anyString(), anyInt()))
+            .thenReturn(changes);
+        mService.getBinderService().clearData("device", 0, false);
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                eq("device"), eq(0), eq(false), eq(true));
+    }
+
+    @Test
+    public void clearDefaultDnDPackageShouldEnableIt() throws RemoteException {
+        ComponentName deviceConfig = new ComponentName("device", "config");
+        ArrayMap<Boolean, ArrayList<ComponentName>> changed = generateResetComponentValues();
+        when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changed);
+        when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changed);
+        mService.getBinderService().clearData("device", 0, false);
+        verify(mConditionProviders, times(1)).resetPackage(
+                        eq("device"), eq(0));
+    }
+
+    @Test
     public void testFlagBubble() throws RemoteException {
         // Bubbles are allowed!
         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);