diff options
| author | 2017-07-21 19:52:50 +0000 | |
|---|---|---|
| committer | 2017-07-21 19:52:50 +0000 | |
| commit | 04964fe0697264fec7628ed98e3e8186a3363e8f (patch) | |
| tree | 73ebe63915a2b90d5db3a72b5b2ddcb2fd4ddf8d | |
| parent | edc3af3f9108f5106b765e960215ec26fd975dc0 (diff) | |
| parent | d1bf5f0108acc4bffdc3a611fabcc23a66f3fb84 (diff) | |
Merge "Fix xml loading for managed services" into oc-mr1-dev
8 files changed, 212 insertions, 200 deletions
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index b22501823020..6ba11b9954c4 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -85,7 +85,7 @@ public class ZenModeConfig implements Parcelable { private static final boolean DEFAULT_ALLOW_SCREEN_ON = true; private static final int XML_VERSION = 2; - private static final String ZEN_TAG = "zen"; + public static final String ZEN_TAG = "zen"; private static final String ZEN_ATT_VERSION = "version"; private static final String ZEN_ATT_USER = "user"; private static final String ALLOW_TAG = "allow"; diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index 5cc14b5ed520..3444ef3ec2fa 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -35,6 +35,7 @@ import android.util.ArraySet; import android.util.Slog; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.notification.NotificationManagerService.DumpFilter; import java.io.PrintWriter; @@ -43,7 +44,8 @@ import java.util.Arrays; public class ConditionProviders extends ManagedServices { - private static final String TAG_ENABLED_DND_APPS = "dnd_apps"; + @VisibleForTesting + static final String TAG_ENABLED_DND_APPS = "dnd_apps"; private final ArrayList<ConditionRecord> mRecords = new ArrayList<>(); private final ArraySet<String> mSystemConditionProviderNames; @@ -84,7 +86,7 @@ public class ConditionProviders extends ManagedServices { c.caption = "condition provider"; c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE; c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES; - c.managedServiceTypeTag = TAG_ENABLED_DND_APPS; + c.xmlTag = TAG_ENABLED_DND_APPS; c.secondarySettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS; c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE; c.settingsAction = Settings.ACTION_CONDITION_PROVIDER_SETTINGS; diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 2f88740cd01b..80878131ae44 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -52,6 +52,7 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import com.android.internal.util.XmlUtils; import com.android.server.notification.NotificationManagerService.DumpFilter; import org.xmlpull.v1.XmlPullParser; @@ -226,7 +227,7 @@ abstract public class ManagedServices { } public void writeXml(XmlSerializer out, boolean forBackup) throws IOException { - out.startTag(null, getConfig().managedServiceTypeTag); + out.startTag(null, getConfig().xmlTag); if (forBackup) { trimApprovedListsAccordingToInstalledServices(); @@ -241,7 +242,7 @@ abstract public class ManagedServices { for (int j = 0; j < M; j++) { final boolean isPrimary = approvedByType.keyAt(j); final Set<String> approved = approvedByType.valueAt(j); - if (approved != null && approved.size() > 0) { + if (approved != null) { String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved); out.startTag(null, TAG_MANAGED_SERVICES); out.attribute(null, ATT_APPROVED_LIST, allowedItems); @@ -260,43 +261,34 @@ abstract public class ManagedServices { } } - out.endTag(null, getConfig().managedServiceTypeTag); + out.endTag(null, getConfig().xmlTag); } - /** - * @return false if modifications were made to the data on load that requires the xml file - * to be re-written - */ - public boolean readXml(XmlPullParser parser) + protected void migrateToXml() { + loadAllowedComponentsFromSettings(); + } + + public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException { - boolean rewriteXml = false; - int type = parser.getEventType(); - String tag = parser.getName(); - if (type != XmlPullParser.START_TAG || !getConfig().managedServiceTypeTag.equals(tag)) { - // xml empty/invalid - read from setting instead - loadAllowedComponentsFromSettings(); - rewriteXml = true; - } else { - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { - tag = parser.getName(); - if (type == XmlPullParser.END_TAG - && getConfig().managedServiceTypeTag.equals(tag)) { - break; - } - if (type == XmlPullParser.START_TAG) { - if (TAG_MANAGED_SERVICES.equals(tag)) { - final String approved = XmlUtils.safeString(parser, ATT_APPROVED_LIST, ""); - final int userId = XmlUtils.safeInt(parser, ATT_USER_ID, 0); - final boolean isPrimary = XmlUtils.safeBool(parser, ATT_IS_PRIMARY, true); - addApprovedList(approved, userId, isPrimary); - } + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { + String tag = parser.getName(); + if (type == XmlPullParser.END_TAG + && getConfig().xmlTag.equals(tag)) { + break; + } + if (type == XmlPullParser.START_TAG) { + if (TAG_MANAGED_SERVICES.equals(tag)) { + final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST); + final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0); + final boolean isPrimary = + XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true); + addApprovedList(approved, userId, isPrimary); + mUseXml = true; } } - mUseXml = true; } rebindServices(false); - - return rewriteXml; } private void loadAllowedComponentsFromSettings() { @@ -1119,7 +1111,7 @@ abstract public class ManagedServices { public String serviceInterface; public String secureSettingName; public String secondarySettingName; - public String managedServiceTypeTag; + public String xmlTag; public String bindPermission; public String settingsAction; public int clientLabel; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index c04124a4b8a0..12ae920f23c7 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -55,7 +55,6 @@ import static android.service.notification.NotificationListenerService.TRIM_LIGH import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; -import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import android.Manifest; import android.annotation.NonNull; @@ -162,6 +161,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.Preconditions; +import com.android.internal.util.XmlUtils; import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import com.android.server.LocalServices; @@ -342,7 +342,7 @@ public class NotificationManagerService extends SystemService { private final UserProfiles mUserProfiles = new UserProfiles(); private NotificationListeners mListeners; - private NotificationAssistants mNotificationAssistants; + private NotificationAssistants mAssistants; private ConditionProviders mConditionProviders; private NotificationUsageStats mUsageStats; @@ -441,24 +441,38 @@ public class NotificationManagerService extends SystemService { } } - private void readPolicyXml(InputStream stream, boolean forRestore) + void readPolicyXml(InputStream stream, boolean forRestore) throws XmlPullParserException, NumberFormatException, IOException { final XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, StandardCharsets.UTF_8.name()); - - boolean saveXml = false; - while (parser.next() != END_DOCUMENT) { - mZenModeHelper.readXml(parser, forRestore); - mRankingHelper.readXml(parser, forRestore); + XmlUtils.beginDocument(parser, TAG_NOTIFICATION_POLICY); + boolean migratedManagedServices = false; + int outerDepth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + if (ZenModeConfig.ZEN_TAG.equals(parser.getName())) { + mZenModeHelper.readXml(parser, forRestore); + } else if (RankingHelper.TAG_RANKING.equals(parser.getName())){ + mRankingHelper.readXml(parser, forRestore); + } // No non-system managed services are allowed on low ram devices if (!ActivityManager.isLowRamDeviceStatic()) { - saveXml |= mListeners.readXml(parser); - saveXml |= mNotificationAssistants.readXml(parser); - saveXml |= mConditionProviders.readXml(parser); + if (mListeners.getConfig().xmlTag.equals(parser.getName())) { + mListeners.readXml(parser); + migratedManagedServices = true; + } else if (mAssistants.getConfig().xmlTag.equals(parser.getName())) { + mAssistants.readXml(parser); + migratedManagedServices = true; + } else if (mConditionProviders.getConfig().xmlTag.equals(parser.getName())) { + mConditionProviders.readXml(parser); + migratedManagedServices = true; + } } } - if (saveXml) { + if (!migratedManagedServices) { + mListeners.migrateToXml(); + mAssistants.migrateToXml(); + mConditionProviders.migrateToXml(); savePolicyFile(); } } @@ -467,7 +481,7 @@ public class NotificationManagerService extends SystemService { if (DBG) Slog.d(TAG, "loadPolicyFile"); synchronized (mPolicyFile) { - FileInputStream infile = null; + InputStream infile = null; try { infile = mPolicyFile.openRead(); readPolicyXml(infile, false /*forRestore*/); @@ -523,7 +537,7 @@ public class NotificationManagerService extends SystemService { mZenModeHelper.writeXml(out, forBackup); mRankingHelper.writeXml(out, forBackup); mListeners.writeXml(out, forBackup); - mNotificationAssistants.writeXml(out, forBackup); + mAssistants.writeXml(out, forBackup); mConditionProviders.writeXml(out, forBackup); out.endTag(null, TAG_NOTIFICATION_POLICY); out.endDocument(); @@ -898,7 +912,7 @@ public class NotificationManagerService extends SystemService { } } mListeners.onPackagesChanged(removingPackage, pkgList, uidList); - mNotificationAssistants.onPackagesChanged(removingPackage, pkgList, uidList); + mAssistants.onPackagesChanged(removingPackage, pkgList, uidList); mConditionProviders.onPackagesChanged(removingPackage, pkgList, uidList); mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList, uidList); savePolicyFile(); @@ -970,7 +984,7 @@ public class NotificationManagerService extends SystemService { // Refresh managed services mConditionProviders.onUserSwitched(user); mListeners.onUserSwitched(user); - mNotificationAssistants.onUserSwitched(user); + mAssistants.onUserSwitched(user); mZenModeHelper.onUserSwitched(user); } else if (action.equals(Intent.ACTION_USER_ADDED)) { mUserProfiles.updateCache(context); @@ -983,7 +997,7 @@ public class NotificationManagerService extends SystemService { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); mConditionProviders.onUserUnlocked(user); mListeners.onUserUnlocked(user); - mNotificationAssistants.onUserUnlocked(user); + mAssistants.onUserUnlocked(user); mZenModeHelper.onUserUnlocked(user); } } @@ -1231,7 +1245,7 @@ public class NotificationManagerService extends SystemService { mListeners = notificationListeners; // This is a MangedServices object that keeps track of the assistant. - mNotificationAssistants = notificationAssistants; + mAssistants = notificationAssistants; mPolicyFile = policyFile; loadPolicyFile(); @@ -1400,7 +1414,7 @@ public class NotificationManagerService extends SystemService { // bind to listener services. mSettingsObserver.observe(); mListeners.onBootPhaseAppsCanStart(); - mNotificationAssistants.onBootPhaseAppsCanStart(); + mAssistants.onBootPhaseAppsCanStart(); mConditionProviders.onBootPhaseAppsCanStart(); } } @@ -1569,7 +1583,6 @@ public class NotificationManagerService extends SystemService { Slog.e(TAG, "Not doing toast. pkg=" + pkg + " callback=" + callback); return ; } - final boolean isSystemToast = isCallerSystemOrPhone() || ("android".equals(pkg)); final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, Binder.getCallingUid()); @@ -1928,7 +1941,7 @@ public class NotificationManagerService extends SystemService { // Listener & assistant mListeners.onPackagesChanged(true, packages, uids); - mNotificationAssistants.onPackagesChanged(true, packages, uids); + mAssistants.onPackagesChanged(true, packages, uids); // Zen mConditionProviders.onPackagesChanged(true, packages, uids); @@ -2134,8 +2147,8 @@ public class NotificationManagerService extends SystemService { long identity = Binder.clearCallingIdentity(); try { ManagedServices manager = - mNotificationAssistants.isComponentEnabledForCurrentProfiles(component) - ? mNotificationAssistants + mAssistants.isComponentEnabledForCurrentProfiles(component) + ? mAssistants : mListeners; manager.setComponentState(component, true); } finally { @@ -2255,7 +2268,7 @@ public class NotificationManagerService extends SystemService { try { synchronized (mNotificationLock) { final ManagedServiceInfo info = - mNotificationAssistants.checkServiceTokenLocked(token); + mAssistants.checkServiceTokenLocked(token); unsnoozeNotificationInt(key, info); } } finally { @@ -2788,7 +2801,7 @@ public class NotificationManagerService extends SystemService { public boolean isNotificationAssistantAccessGranted(ComponentName assistant) { Preconditions.checkNotNull(assistant); checkCallerIsSystemOrSameApp(assistant.getPackageName()); - return mNotificationAssistants.isPackageOrComponentAllowed(assistant.flattenToString(), + return mAssistants.isPackageOrComponentAllowed(assistant.flattenToString(), getCallingUserHandle().getIdentifier()); } @@ -2835,7 +2848,7 @@ public class NotificationManagerService extends SystemService { if (!mActivityManager.isLowRamDevice()) { mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(), userId, false, granted); - mNotificationAssistants.setPackageOrComponentEnabled(assistant.flattenToString(), + mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(), userId, true, granted); getContext().sendBroadcastAsUser(new Intent( @@ -2854,7 +2867,7 @@ public class NotificationManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { synchronized (mNotificationLock) { - mNotificationAssistants.checkServiceTokenLocked(token); + mAssistants.checkServiceTokenLocked(token); int N = mEnqueuedNotifications.size(); for (int i = 0; i < N; i++) { final NotificationRecord n = mEnqueuedNotifications.get(i); @@ -2876,7 +2889,7 @@ public class NotificationManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { synchronized (mNotificationLock) { - mNotificationAssistants.checkServiceTokenLocked(token); + mAssistants.checkServiceTokenLocked(token); NotificationRecord n = mNotificationsByKey.get(adjustment.getKey()); applyAdjustment(n, adjustment); } @@ -2893,7 +2906,7 @@ public class NotificationManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { synchronized (mNotificationLock) { - mNotificationAssistants.checkServiceTokenLocked(token); + mAssistants.checkServiceTokenLocked(token); for (Adjustment adjustment : adjustments) { NotificationRecord n = mNotificationsByKey.get(adjustment.getKey()); applyAdjustment(n, adjustment); @@ -3273,7 +3286,7 @@ public class NotificationManagerService extends SystemService { } pw.println(')'); pw.println("\n Notification assistant services:"); - mNotificationAssistants.dump(pw, filter); + mAssistants.dump(pw, filter); } if (!filter.filtered || zenOnly) { @@ -3664,7 +3677,7 @@ public class NotificationManagerService extends SystemService { cancelNotificationLocked(r, false, REASON_SNOOZED, wasPosted); updateLightsLocked(); if (mSnoozeCriterionId != null) { - mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn, mSnoozeCriterionId); + mAssistants.notifyAssistantSnoozedLocked(r.sbn, mSnoozeCriterionId); mSnoozeHelper.snooze(r); } else { mSnoozeHelper.snooze(r, mDuration); @@ -3728,8 +3741,8 @@ public class NotificationManagerService extends SystemService { mRankingHelper.extractSignals(r); // tell the assistant service about the notification - if (mNotificationAssistants.isEnabled()) { - mNotificationAssistants.onNotificationEnqueued(r); + if (mAssistants.isEnabled()) { + mAssistants.onNotificationEnqueued(r); mHandler.postDelayed(new PostNotificationRunnable(r.getKey()), DELAY_FOR_ASSISTANT_TIME); } else { @@ -5238,7 +5251,7 @@ public class NotificationManagerService extends SystemService { Config c = new Config(); c.caption = "notification assistant service"; c.serviceInterface = NotificationAssistantService.SERVICE_INTERFACE; - c.managedServiceTypeTag = TAG_ENABLED_NOTIFICATION_ASSISTANTS; + c.xmlTag = TAG_ENABLED_NOTIFICATION_ASSISTANTS; c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT; c.bindPermission = Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE; c.settingsAction = Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS; @@ -5350,7 +5363,7 @@ public class NotificationManagerService extends SystemService { Config c = new Config(); c.caption = "notification listener"; c.serviceInterface = NotificationListenerService.SERVICE_INTERFACE; - c.managedServiceTypeTag = TAG_ENABLED_NOTIFICATION_LISTENERS; + c.xmlTag = TAG_ENABLED_NOTIFICATION_LISTENERS; c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS; c.bindPermission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE; c.settingsAction = Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS; diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 0d5cc2c112d5..f48dc48d36ef 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -20,6 +20,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.util.Preconditions; +import com.android.internal.util.XmlUtils; import android.app.Notification; import android.app.NotificationChannel; @@ -64,7 +65,7 @@ public class RankingHelper implements RankingConfig { private static final int XML_VERSION = 1; - private static final String TAG_RANKING = "ranking"; + static final String TAG_RANKING = "ranking"; private static final String TAG_PACKAGE = "package"; private static final String TAG_CHANNEL = "channel"; private static final String TAG_GROUP = "channelGroup"; @@ -169,7 +170,7 @@ public class RankingHelper implements RankingConfig { } if (type == XmlPullParser.START_TAG) { if (TAG_PACKAGE.equals(tag)) { - int uid = XmlUtils.safeInt(parser, ATT_UID, Record.UNKNOWN_UID); + int uid = XmlUtils.readIntAttribute(parser, ATT_UID, Record.UNKNOWN_UID); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { if (forRestore) { @@ -182,14 +183,21 @@ public class RankingHelper implements RankingConfig { } Record r = getOrCreateRecord(name, uid, - XmlUtils.safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE), - XmlUtils.safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY), - XmlUtils.safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY), - XmlUtils.safeBool(parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE)); - r.importance = XmlUtils.safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); - r.priority = XmlUtils.safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); - r.visibility = XmlUtils.safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); - r.showBadge = XmlUtils.safeBool(parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE); + XmlUtils.readIntAttribute( + parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE), + XmlUtils.readIntAttribute(parser, ATT_PRIORITY, DEFAULT_PRIORITY), + XmlUtils.readIntAttribute( + parser, ATT_VISIBILITY, DEFAULT_VISIBILITY), + XmlUtils.readBooleanAttribute( + parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE)); + r.importance = XmlUtils.readIntAttribute( + parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); + r.priority = XmlUtils.readIntAttribute( + parser, ATT_PRIORITY, DEFAULT_PRIORITY); + r.visibility = XmlUtils.readIntAttribute( + parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); + r.showBadge = XmlUtils.readBooleanAttribute( + parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE); final int innerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT @@ -214,7 +222,7 @@ public class RankingHelper implements RankingConfig { if (TAG_CHANNEL.equals(tagName)) { String id = parser.getAttributeValue(null, ATT_ID); String channelName = parser.getAttributeValue(null, ATT_NAME); - int channelImportance = XmlUtils.safeInt( + int channelImportance = XmlUtils.readIntAttribute( parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); if (!TextUtils.isEmpty(id) && !TextUtils.isEmpty(channelName)) { NotificationChannel channel = new NotificationChannel(id, diff --git a/services/core/java/com/android/server/notification/XmlUtils.java b/services/core/java/com/android/server/notification/XmlUtils.java deleted file mode 100644 index 831d03970fe3..000000000000 --- a/services/core/java/com/android/server/notification/XmlUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.notification; - -import android.annotation.NonNull; -import android.text.TextUtils; - -import org.xmlpull.v1.XmlPullParser; - -class XmlUtils { - - static @NonNull String safeString(XmlPullParser parser, String att, String defValue) { - final String value = parser.getAttributeValue(null, att); - if (value == null) return defValue; - return value; - } - - static @NonNull boolean safeBool(XmlPullParser parser, String att, boolean defValue) { - final String value = parser.getAttributeValue(null, att); - if (TextUtils.isEmpty(value)) return defValue; - return Boolean.parseBoolean(value); - } - - static @NonNull int safeInt(XmlPullParser parser, String att, int defValue) { - final String val = parser.getAttributeValue(null, att); - return tryParseInt(val, defValue); - } - - private static int tryParseInt(String value, int defValue) { - if (TextUtils.isEmpty(value)) return defValue; - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return defValue; - } - } - -} diff --git a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java index ffbd8d493899..bd65f571d20b 100644 --- a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java @@ -170,7 +170,7 @@ public class ManagedServicesTest extends NotificationTestCase { null); writeExpectedValuesToSettings(approvalLevel); - assertTrue(service.readXml(parser)); + service.migrateToXml(); verifyExpectedApprovedEntries(service); } @@ -182,7 +182,7 @@ public class ManagedServicesTest extends NotificationTestCase { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); - assertFalse(loadXml(service)); + loadXml(service); verifyExpectedApprovedEntries(service); } @@ -239,7 +239,7 @@ public class ManagedServicesTest extends NotificationTestCase { parser.setInput(new BufferedInputStream( new ByteArrayInputStream(baos.toByteArray())), null); parser.nextTag(); - assertFalse(service.readXml(parser)); + service.readXml(parser); verifyExpectedApprovedEntries(service); assertFalse(service.isPackageOrComponentAllowed("this.is.a.package.name", 0)); @@ -341,11 +341,8 @@ public class ManagedServicesTest extends NotificationTestCase { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})), - null); writeExpectedValuesToSettings(approvalLevel); - service.readXml(parser); + service.migrateToXml(); mExpectedPrimaryPackages.put(0, "another.package"); mExpectedPrimaryComponentNames.put(0, "another.package/B1"); @@ -360,11 +357,8 @@ public class ManagedServicesTest extends NotificationTestCase { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})), - null); writeExpectedValuesToSettings(approvalLevel); - service.readXml(parser); + service.migrateToXml(); mExpectedSecondaryComponentNames.put(10, "component/2"); mExpectedSecondaryPackages.put(10, "component"); @@ -516,9 +510,9 @@ public class ManagedServicesTest extends NotificationTestCase { assertEquals(0, service.getAllowedComponents(10).size()); } - private boolean loadXml(ManagedServices service) throws Exception { + private void loadXml(ManagedServices service) throws Exception { final StringBuffer xml = new StringBuffer(); - xml.append("<" + service.getConfig().managedServiceTypeTag + ">\n"); + xml.append("<" + service.getConfig().xmlTag + ">\n"); for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) { xml.append(getXmlEntry( mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true)); @@ -527,13 +521,13 @@ public class ManagedServicesTest extends NotificationTestCase { xml.append(getXmlEntry( mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false)); } - xml.append("</" + service.getConfig().managedServiceTypeTag + ">"); + xml.append("</" + service.getConfig().xmlTag + ">"); XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream( new ByteArrayInputStream(xml.toString().getBytes())), null); parser.nextTag(); - return service.readXml(parser); + service.readXml(parser); } private void addExpectedServices(final ManagedServices service, final List<String> packages, @@ -674,7 +668,7 @@ public class ManagedServicesTest extends NotificationTestCase { @Override protected Config getConfig() { final Config c = new Config(); - c.managedServiceTypeTag= "test"; + c.xmlTag = "test"; c.secureSettingName = SETTING; c.secondarySettingName = SECONDARY_SETTING; c.bindPermission = "permission"; diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index d462c2ff1a6a..c1cb92e4bfe3 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -20,9 +20,6 @@ import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static com.android.server.notification.NotificationManagerService - .MESSAGE_SEND_RANKING_UPDATE; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -34,12 +31,10 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -60,35 +55,34 @@ import android.content.pm.ParceledListSlice; import android.graphics.Color; import android.media.AudioManager; import android.os.Binder; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; import android.os.Process; import android.os.UserHandle; import android.provider.Settings.Secure; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; +import android.service.notification.ZenModeConfig; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.ArrayMap; import android.util.AtomicFile; -import android.util.Log; -import android.util.Slog; import com.android.server.lights.Light; import com.android.server.lights.LightsManager; +import com.android.server.notification.NotificationManagerService.NotificationAssistants; +import com.android.server.notification.NotificationManagerService.NotificationListeners; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -115,7 +109,6 @@ public class NotificationManagerServiceTest extends NotificationTestCase { private TestableLooper mTestableLooper; @Mock private RankingHelper mRankingHelper; - @Mock AtomicFile mPolicyFile; File mFile; @Mock @@ -129,8 +122,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase { private NotificationChannel mTestNotificationChannel = new NotificationChannel( TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT); @Mock - private NotificationManagerService.NotificationListeners mNotificationListeners; - @Mock private NotificationManagerService.NotificationAssistants mNotificationAssistants; + private NotificationListeners mListeners; + @Mock private NotificationAssistants mAssistants; @Mock private ConditionProviders mConditionProviders; private ManagedServices.ManagedServiceInfo mListener; @Mock private ICompanionDeviceManager mCompanionMgr; @@ -182,18 +175,34 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class)); when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); + // write to a test file; the system file isn't readable from tests mFile = new File(mContext.getCacheDir(), "test.xml"); mFile.createNewFile(); - when(mPolicyFile.openRead()).thenReturn(new FileInputStream(mFile)); - when(mPolicyFile.startWrite()).thenReturn(new FileOutputStream(mFile)); - - mListener = mNotificationListeners.new ManagedServiceInfo( + final String preupgradeXml = "<notification-policy></notification-policy>"; + mPolicyFile = new AtomicFile(mFile); + FileOutputStream fos = mPolicyFile.startWrite(); + fos.write(preupgradeXml.getBytes()); + mPolicyFile.finishWrite(fos); + FileInputStream fStream = new FileInputStream(mFile); + + // Setup managed services + mListener = mListeners.new ManagedServiceInfo( null, new ComponentName(PKG, "test_class"), mUid, true, null, 0); - when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + ManagedServices.Config listenerConfig = new ManagedServices.Config(); + listenerConfig.xmlTag = NotificationListeners.TAG_ENABLED_NOTIFICATION_LISTENERS; + when(mListeners.getConfig()).thenReturn(listenerConfig); + ManagedServices.Config assistantConfig = new ManagedServices.Config(); + assistantConfig.xmlTag = NotificationAssistants.TAG_ENABLED_NOTIFICATION_ASSISTANTS; + when(mAssistants.getConfig()).thenReturn(assistantConfig); + ManagedServices.Config dndConfig = new ManagedServices.Config(); + dndConfig.xmlTag = ConditionProviders.TAG_ENABLED_DND_APPS; + when(mConditionProviders.getConfig()).thenReturn(dndConfig); + try { mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager, mPackageManagerClient, mockLightsManager, - mNotificationListeners, mNotificationAssistants, mConditionProviders, + mListeners, mAssistants, mConditionProviders, mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper); } catch (SecurityException e) { @@ -827,13 +836,13 @@ public class NotificationManagerServiceTest extends NotificationTestCase { eq(channel2.getId()), anyBoolean())) .thenReturn(channel2); - reset(mNotificationListeners); + reset(mListeners); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); - verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); - verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(channel2), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); } @@ -847,13 +856,13 @@ public class NotificationManagerServiceTest extends NotificationTestCase { NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b"); NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m"); - reset(mNotificationListeners); + reset(mListeners); mBinderService.createNotificationChannelGroups(PKG, new ParceledListSlice(Arrays.asList(group1, group2))); - verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), eq(Process.myUserHandle()), eq(group1), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); - verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), eq(Process.myUserHandle()), eq(group2), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); } @@ -869,9 +878,9 @@ public class NotificationManagerServiceTest extends NotificationTestCase { eq(mTestNotificationChannel.getId()), anyBoolean())) .thenReturn(mTestNotificationChannel); - reset(mNotificationListeners); + reset(mListeners); mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel); - verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @@ -885,9 +894,9 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean())) .thenReturn(mTestNotificationChannel); - reset(mNotificationListeners); + reset(mListeners); mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId()); - verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); } @@ -901,9 +910,9 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mNotificationManagerService.setRankingHelper(mRankingHelper); when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt())) .thenReturn(ncg); - reset(mNotificationListeners); + reset(mListeners); mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId()); - verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), + verify(mListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG), eq(Process.myUserHandle()), eq(ncg), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED)); } @@ -920,7 +929,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any()); - verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @@ -941,7 +950,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any()); - verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @@ -955,7 +964,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mListener = mock(ManagedServices.ManagedServiceInfo.class); mListener.component = new ComponentName(PKG, PKG); when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); - when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); try { mBinderService.updateNotificationChannelFromPrivilegedListener( @@ -967,7 +976,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any()); - verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @@ -1012,7 +1021,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); mListener = mock(ManagedServices.ManagedServiceInfo.class); when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); - when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); try { mBinderService.getNotificationChannelsFromPrivilegedListener( @@ -1063,7 +1072,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations); mListener = mock(ManagedServices.ManagedServiceInfo.class); when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false); - when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); + when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener); try { mBinderService.getNotificationChannelGroupsFromPrivilegedListener( @@ -1232,11 +1241,11 @@ public class NotificationManagerServiceTest extends NotificationTestCase { } } - verify(mNotificationListeners, times(1)).setPackageOrComponentEnabled( + verify(mListeners, times(1)).setPackageOrComponentEnabled( c.flattenToString(), 0, true, true); verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( c.flattenToString(), 0, false, true); - verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( + verify(mAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1251,11 +1260,11 @@ public class NotificationManagerServiceTest extends NotificationTestCase { } } - verify(mNotificationAssistants, times(1)).setPackageOrComponentEnabled( + verify(mAssistants, times(1)).setPackageOrComponentEnabled( c.flattenToString(), 0, true, true); verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( c.flattenToString(), 0, false, true); - verify(mNotificationListeners, never()).setPackageOrComponentEnabled( + verify(mListeners, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1272,9 +1281,9 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mConditionProviders, times(1)).setPackageOrComponentEnabled( c.getPackageName(), 0, true, true); - verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( + verify(mAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); - verify(mNotificationListeners, never()).setPackageOrComponentEnabled( + verify(mListeners, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1284,11 +1293,11 @@ public class NotificationManagerServiceTest extends NotificationTestCase { ComponentName c = ComponentName.unflattenFromString("package/Component"); mBinderService.setNotificationListenerAccessGranted(c, true); - verify(mNotificationListeners, never()).setPackageOrComponentEnabled( + verify(mListeners, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, true, true); verify(mConditionProviders, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, false, true); - verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( + verify(mAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1299,11 +1308,11 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mBinderService.setNotificationAssistantAccessGranted(c, true); - verify(mNotificationListeners, never()).setPackageOrComponentEnabled( + verify(mListeners, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, true, true); verify(mConditionProviders, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, false, true); - verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( + verify(mAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1313,11 +1322,11 @@ public class NotificationManagerServiceTest extends NotificationTestCase { ComponentName c = ComponentName.unflattenFromString("package/Component"); mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true); - verify(mNotificationListeners, never()).setPackageOrComponentEnabled( + verify(mListeners, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, true, true); verify(mConditionProviders, never()).setPackageOrComponentEnabled( c.flattenToString(), 0, false, true); - verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( + verify(mAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } @@ -1470,4 +1479,50 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mNotificationManagerService.handleRankingSort(); verify(handler, never()).scheduleSendRankingUpdate(); } + + @Test + public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception { + final String preupgradeXml = "<notification-policy version=\"1\">" + + "<zen></zen>" + + "<ranking></ranking>" + + "<enabled_listeners>" + + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" + + "</enabled_listeners>" + + "<enabled_assistants>" + + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" + + "</enabled_assistants>" + + "<dnd_apps>" + + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />" + + "</dnd_apps>" + + "</notification-policy>"; + mNotificationManagerService.readPolicyXml( + new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), false); + verify(mListeners, times(1)).readXml(any()); + verify(mConditionProviders, times(1)).readXml(any()); + verify(mAssistants, times(1)).readXml(any()); + + // numbers are inflated for setup + verify(mListeners, times(1)).migrateToXml(); + verify(mConditionProviders, times(1)).migrateToXml(); + verify(mAssistants, times(1)).migrateToXml(); + } + + @Test + public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception { + final String preupgradeXml = "<notification-policy version=\"1\">" + + "<zen></zen>" + + "<ranking></ranking>" + + "</notification-policy>"; + mNotificationManagerService.readPolicyXml( + new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), false); + verify(mListeners, never()).readXml(any()); + verify(mConditionProviders, never()).readXml(any()); + verify(mAssistants, never()).readXml(any()); + + // numbers are inflated for setup + verify(mListeners, times(2)).migrateToXml(); + verify(mConditionProviders, times(2)).migrateToXml(); + verify(mAssistants, times(2)).migrateToXml(); + } + } |