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 */);