/*
 * 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 static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.IBinder;
import android.os.IInterface;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.SparseArray;
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.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class ManagedServicesTest extends UiServiceTestCase {

    @Mock
    private IPackageManager mIpm;
    @Mock
    private PackageManager mPm;
    @Mock
    private UserManager mUm;
    @Mock
    private ManagedServices.UserProfiles mUserProfiles;
    Object mLock = new Object();

    UserInfo mZero = new UserInfo(0, "zero", 0);
    UserInfo mTen = new UserInfo(10, "ten", 0);
    private String mDefaultsString;
    private String mVersionString;
    private final Set<ComponentName> mDefaults = new ArraySet();
    private ManagedServices mService;

    private static final String SETTING = "setting";
    private static final String SECONDARY_SETTING = "secondary_setting";

    private ArrayMap<Integer, String> mExpectedPrimaryPackages;
    private ArrayMap<Integer, String> mExpectedPrimaryComponentNames;
    private ArrayMap<Integer, String> mExpectedSecondaryPackages;
    private ArrayMap<Integer, String> mExpectedSecondaryComponentNames;

    // type : user : list of approved
    private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary;
    private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        getContext().setMockPackageManager(mPm);
        getContext().addMockSystemService(Context.USER_SERVICE, mUm);

        List<UserInfo> users = new ArrayList<>();
        users.add(mZero);
        users.add(mTen);
        users.add(new UserInfo(11, "11", 0));
        users.add(new UserInfo(12, "12", 0));
        for (UserInfo user : users) {
            when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
        }
        when(mUm.getUsers()).thenReturn(users);
        IntArray profileIds = new IntArray();
        profileIds.add(0);
        profileIds.add(11);
        profileIds.add(10);
        profileIds.add(12);
        when(mUserProfiles.getCurrentProfileIds()).thenReturn(profileIds);

        mVersionString = "2";
        mExpectedPrimary = new ArrayMap<>();
        mExpectedSecondary = new ArrayMap<>();
        mExpectedPrimaryPackages = new ArrayMap<>();
        mExpectedPrimaryPackages.put(0, "this.is.a.package.name:another.package");
        mExpectedPrimaryPackages.put(10, "this.is.another.package");
        mExpectedPrimaryPackages.put(11, "");
        mExpectedPrimaryPackages.put(12, "bananas!");
        mExpectedPrimaryComponentNames = new ArrayMap<>();
        mExpectedPrimaryComponentNames.put(0, "this.is.a.package.name/Ba:another.package/B1");
        mExpectedPrimaryComponentNames.put(10, "this.is.another.package/M1");
        mExpectedPrimaryComponentNames.put(11, "");
        mExpectedPrimaryComponentNames.put(12, "bananas!/Bananas!");
        mExpectedPrimary.put(APPROVAL_BY_PACKAGE, mExpectedPrimaryPackages);
        mExpectedPrimary.put(APPROVAL_BY_COMPONENT, mExpectedPrimaryComponentNames);

        mExpectedSecondaryComponentNames = new ArrayMap<>();
        mExpectedSecondaryComponentNames.put(0, "secondary/component.Name");
        mExpectedSecondaryComponentNames.put(10,
                "this.is.another.package/with.Component:component/2:package/component2");
        mExpectedSecondaryPackages = new ArrayMap<>();
        mExpectedSecondaryPackages.put(0, "secondary");
        mExpectedSecondaryPackages.put(10,
                "this.is.another.package:component:package");
        mExpectedSecondary.put(APPROVAL_BY_PACKAGE, mExpectedSecondaryPackages);
        mExpectedSecondary.put(APPROVAL_BY_COMPONENT, mExpectedSecondaryComponentNames);
        mService = new TestManagedServices(getContext(), mLock, mUserProfiles,
                mIpm, APPROVAL_BY_COMPONENT);
    }

    @Test
    public void testBackupAndRestore_migration() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);

            for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
                service.onSettingRestored(
                        service.getConfig().secureSettingName,
                        mExpectedPrimary.get(approvalLevel).get(userId),
                        Build.VERSION_CODES.O, userId);
            }
            verifyExpectedApprovedEntries(service, true);

            for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
                service.onSettingRestored(service.getConfig().secondarySettingName,
                        mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
                        userId);
            }
            verifyExpectedApprovedEntries(service);
        }
    }

    @Test
    public void testBackupAndRestore_migration_preO() throws Exception {
        ArrayMap<Integer, String> backupPrimaryPackages = new ArrayMap<>();
        backupPrimaryPackages.put(0, "backup.0:backup:0a");
        backupPrimaryPackages.put(10, "10.backup");
        backupPrimaryPackages.put(11, "eleven");
        backupPrimaryPackages.put(12, "");
        ArrayMap<Integer, String> backupPrimaryComponentNames = new ArrayMap<>();
        backupPrimaryComponentNames.put(0, "backup.first/whatever:a/b");
        backupPrimaryComponentNames.put(10, "again/M1");
        backupPrimaryComponentNames.put(11, "orange/youglad:itisnot/banana");
        backupPrimaryComponentNames.put(12, "");
        ArrayMap<Integer, ArrayMap<Integer, String>> backupPrimary = new ArrayMap<>();
        backupPrimary.put(APPROVAL_BY_PACKAGE, backupPrimaryPackages);
        backupPrimary.put(APPROVAL_BY_COMPONENT, backupPrimaryComponentNames);

        ArrayMap<Integer, String> backupSecondaryComponentNames = new ArrayMap<>();
        backupSecondaryComponentNames.put(0, "secondary.1/component.Name");
        backupSecondaryComponentNames.put(10,
                "this.is.another.package.backup/with.Component:component.backup/2");
        ArrayMap<Integer, String> backupSecondaryPackages = new ArrayMap<>();
        backupSecondaryPackages.put(0, "");
        backupSecondaryPackages.put(10,
                "this.is.another.package.backup:package.backup");
        ArrayMap<Integer, ArrayMap<Integer, String>> backupSecondary = new ArrayMap<>();
        backupSecondary.put(APPROVAL_BY_PACKAGE, backupSecondaryPackages);
        backupSecondary.put(APPROVAL_BY_COMPONENT, backupSecondaryComponentNames);

        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);

            // not an expected flow but a way to get data into the settings
            for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
                service.onSettingRestored(
                        service.getConfig().secureSettingName,
                        mExpectedPrimary.get(approvalLevel).get(userId),
                        Build.VERSION_CODES.O, userId);
            }

            for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
                service.onSettingRestored(service.getConfig().secondarySettingName,
                        mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
                        userId);
            }

            // actual test
            for (int userId : backupPrimary.get(approvalLevel).keySet()) {
                service.onSettingRestored(
                        service.getConfig().secureSettingName,
                        backupPrimary.get(approvalLevel).get(userId),
                        Build.VERSION_CODES.N_MR1, userId);
            }
            verifyExpectedApprovedEntries(service, true);

            for (int userId : backupSecondary.get(approvalLevel).keySet()) {
                service.onSettingRestored(service.getConfig().secondarySettingName,
                        backupSecondary.get(approvalLevel).get(userId),
                        Build.VERSION_CODES.N_MR1, userId);
            }
            verifyExpectedApprovedEntries(service);
            verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel));
            verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel));
        }
    }

    @Test
    public void testReadXml_migrationFromSettings() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);

            // approved services aren't in xml
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})),
                    null);
            writeExpectedValuesToSettings(approvalLevel);

            service.migrateToXml();

            verifyExpectedApprovedEntries(service);
        }
    }

    @Test
    public void testReadXml() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);

            loadXml(service);

            verifyExpectedApprovedEntries(service);

            int[] invalidUsers = new int[] {98, 99};
            for (int invalidUser : invalidUsers) {
                assertFalse("service type " + service.mApprovalLevel + ":"
                                + invalidUser + " is allowed for user " + invalidUser,
                        service.isPackageOrComponentAllowed(
                                String.valueOf(invalidUser), invalidUser));
            }
        }
    }

    @Test
    public void testReadXml_appendsListOfApprovedComponents() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);

            String preApprovedPackage = "some.random.package";
            String preApprovedComponent = "some.random.package/C1";

            List<String> packages = new ArrayList<>();
            packages.add(preApprovedPackage);
            addExpectedServices(service, packages, 0);

            service.setPackageOrComponentEnabled(preApprovedComponent, 0, true, true);

            loadXml(service);

            verifyExpectedApprovedEntries(service);

            String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
                    ? preApprovedComponent
                    : preApprovedPackage;
            assertTrue(service.isPackageOrComponentAllowed(verifyValue, 0));
        }
    }

    /** Test that restore ignores the user id attribute and applies the data to the target user. */
    @Test
    public void testReadXml_onlyRestoresForTargetUser() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service =
                    new TestManagedServices(
                            getContext(), mLock, mUserProfiles, mIpm, approvalLevel);
            String testPackage = "user.test.package";
            String testComponent = "user.test.component/C1";
            String resolvedValue =
                    (approvalLevel == APPROVAL_BY_COMPONENT) ? testComponent : testPackage;
            XmlPullParser parser =
                    getParserWithEntries(service, getXmlEntry(resolvedValue, 0, true));

            service.readXml(parser, null, true, 10);

            assertFalse(service.isPackageOrComponentAllowed(resolvedValue, 0));
            assertTrue(service.isPackageOrComponentAllowed(resolvedValue, 10));
        }
    }

    /** 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 {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service =
                    new TestManagedServices(
                            getContext(), mLock, mUserProfiles, mIpm, approvalLevel);
            // Set up components.
            String testPackage0 = "user0.test.package";
            String testComponent0 = "user0.test.component/C1";
            String testPackage10 = "user10.test.package";
            String testComponent10 = "user10.test.component/C1";
            String resolvedValue0 =
                    (approvalLevel == APPROVAL_BY_COMPONENT) ? testComponent0 : testPackage0;
            String resolvedValue10 =
                    (approvalLevel == APPROVAL_BY_COMPONENT) ? testComponent10 : testPackage10;
            addExpectedServices(
                    service, Collections.singletonList(service.getPackageName(resolvedValue0)), 0);
            addExpectedServices(
                    service,
                    Collections.singletonList(service.getPackageName(resolvedValue10)),
                    10);
            XmlPullParser parser =
                    getParserWithEntries(
                            service,
                            getXmlEntry(resolvedValue0, 0, true),
                            getXmlEntry(resolvedValue10, 10, true));
            service.readXml(parser, null, false, UserHandle.USER_ALL);

            // Write backup.
            XmlSerializer serializer = new FastXmlSerializer();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
            serializer.startDocument(null, true);
            service.writeXml(serializer, true, 10);
            serializer.endDocument();
            serializer.flush();

            // Reset values.
            service.setPackageOrComponentEnabled(resolvedValue0, 0, true, false);
            service.setPackageOrComponentEnabled(resolvedValue10, 10, true, false);

            // Parse backup via restore.
            XmlPullParser restoreParser = Xml.newPullParser();
            restoreParser.setInput(
                    new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), null);
            restoreParser.nextTag();
            service.readXml(restoreParser, null, true, 10);

            assertFalse(service.isPackageOrComponentAllowed(resolvedValue0, 0));
            assertFalse(service.isPackageOrComponentAllowed(resolvedValue0, 10));
            assertTrue(service.isPackageOrComponentAllowed(resolvedValue10, 10));
        }
    }

    @Test
    public void testWriteXml_trimsMissingServices() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            loadXml(service);

            // remove missing
            mExpectedPrimaryPackages.put(0, "another.package");
            mExpectedPrimaryPackages.remove(12);
            mExpectedPrimaryComponentNames.put(0, "another.package/B1");
            mExpectedPrimaryComponentNames.remove(12);
            mExpectedSecondaryPackages.put(10, "this.is.another.package:component");
            mExpectedSecondaryComponentNames.put(
                    10, "this.is.another.package/with.Component:component/2");

            for (UserInfo userInfo : mUm.getUsers()) {
                List<String> entriesExpectedToHaveServices = new ArrayList<>();
                if (mExpectedPrimary.get(approvalLevel).containsKey(userInfo.id)) {
                    for (String packageOrComponent :
                            mExpectedPrimary.get(approvalLevel).get(userInfo.id).split(":")) {
                        if (!TextUtils.isEmpty(packageOrComponent)) {
                            entriesExpectedToHaveServices.add(
                                    service.getPackageName(packageOrComponent));
                        }
                    }
                }
                if (mExpectedSecondary.get(approvalLevel).containsKey(userInfo.id)) {
                    for (String packageOrComponent :
                            mExpectedSecondary.get(approvalLevel).get(userInfo.id).split(":")) {
                        if (!TextUtils.isEmpty(packageOrComponent)) {
                            entriesExpectedToHaveServices.add(
                                    service.getPackageName(packageOrComponent));
                        }
                    }
                }
                addExpectedServices(service, entriesExpectedToHaveServices, userInfo.id);
            }

            XmlSerializer serializer = new FastXmlSerializer();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
            serializer.startDocument(null, true);
            for (UserInfo userInfo : mUm.getUsers()) {
                service.writeXml(serializer, true, userInfo.id);
            }
            serializer.endDocument();
            serializer.flush();

            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new BufferedInputStream(
                    new ByteArrayInputStream(baos.toByteArray())), null);
            parser.nextTag();
            for (UserInfo userInfo : mUm.getUsers()) {
                service.readXml(parser, null, true, userInfo.id);
            }

            verifyExpectedApprovedEntries(service);
            assertFalse(service.isPackageOrComponentAllowed("this.is.a.package.name", 0));
            assertFalse(service.isPackageOrComponentAllowed("bananas!", 12));
            assertFalse(service.isPackageOrComponentAllowed("package/component2", 10));
        }
    }

    @Test
    public void testWriteXml_writesSetting() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            loadXml(service);

            XmlSerializer serializer = new FastXmlSerializer();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
            serializer.startDocument(null, true);
            service.writeXml(serializer, false, UserHandle.USER_ALL);
            serializer.endDocument();
            serializer.flush();

            for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) {
                List<String> expected =
                        stringToList(mExpectedPrimary.get(approvalLevel).get(userId));
                List<String> actual = stringToList(Settings.Secure.getStringForUser(
                        getContext().getContentResolver(),
                        service.getConfig().secureSettingName, userId));
                assertContentsInAnyOrder(actual, expected);
            }
        }
    }

    @Test
    public void rebindServices_onlyBindsExactMatchesIfComponent() throws Exception {
        // If the primary and secondary lists contain component names, only those components within
        // the package should be matched
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                mIpm,
                ManagedServices.APPROVAL_BY_COMPONENT);

        List<String> packages = new ArrayList<>();
        packages.add("package");
        packages.add("anotherPackage");
        addExpectedServices(service, packages, 0);

        // only 2 components are approved per package
        mExpectedPrimaryComponentNames.clear();
        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
        mExpectedSecondaryComponentNames.clear();
        mExpectedSecondaryComponentNames.put(0, "anotherPackage/C1:anotherPackage/C2");

        loadXml(service);

        // verify the 2 components per package are enabled (bound)
        verifyExpectedBoundEntries(service, true);
        verifyExpectedBoundEntries(service, false);

        // verify the last component per package is not enabled/we don't try to bind to it
        for (String pkg : packages) {
            ComponentName unapprovedAdditionalComponent =
                    ComponentName.unflattenFromString(pkg + "/C3");
            assertFalse(
                    service.isComponentEnabledForCurrentProfiles(
                            unapprovedAdditionalComponent));
            verify(mIpm, never()).getServiceInfo(
                    eq(unapprovedAdditionalComponent), anyInt(), anyInt());
        }
    }

    @Test
    public void rebindServices_bindsEverythingInAPackage() throws Exception {
        // If the primary and secondary lists contain packages, all components within those packages
        // should be bound
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_PACKAGE);

        List<String> packages = new ArrayList<>();
        packages.add("package");
        packages.add("packagea");
        addExpectedServices(service, packages, 0);

        // 2 approved packages
        mExpectedPrimaryPackages.clear();
        mExpectedPrimaryPackages.put(0, "package");
        mExpectedSecondaryPackages.clear();
        mExpectedSecondaryPackages.put(0, "packagea");

        loadXml(service);

        // verify the 3 components per package are enabled (bound)
        verifyExpectedBoundEntries(service, true);
        verifyExpectedBoundEntries(service, false);
    }

    @Test
    public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            writeExpectedValuesToSettings(approvalLevel);
            service.migrateToXml();

            mExpectedPrimaryPackages.put(0, "another.package");
            mExpectedPrimaryComponentNames.put(0, "another.package/B1");
            service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, new int[]{103});

            verifyExpectedApprovedEntries(service);
        }
    }

    @Test
    public void testPackageUninstall_componentNoLongerInApprovedList() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            writeExpectedValuesToSettings(approvalLevel);
            service.migrateToXml();

            mExpectedSecondaryComponentNames.put(10, "component/2");
            mExpectedSecondaryPackages.put(10, "component");
            service.onPackagesChanged(true, new String[]{"this.is.another.package"}, new int[]{
                    UserHandle.PER_USER_RANGE + 1});

            verifyExpectedApprovedEntries(service);
        }
    }

    @Test
    public void testIsPackageAllowed() {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            writeExpectedValuesToSettings(approvalLevel);
            service.migrateToXml();

            verifyExpectedApprovedPackages(service);
        }
    }

    @Test
    public void testUpgradeAppBindsNewServices() throws Exception {
        // If the primary and secondary lists contain component names, only those components within
        // the package should be matched
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                mIpm,
                ManagedServices.APPROVAL_BY_PACKAGE);

        List<String> packages = new ArrayList<>();
        packages.add("package");
        addExpectedServices(service, packages, 0);

        // only 2 components are approved per package
        mExpectedPrimaryComponentNames.clear();
        mExpectedPrimaryPackages.clear();
        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
        mExpectedSecondaryComponentNames.clear();
        mExpectedSecondaryPackages.clear();

        loadXml(service);

        // new component expected
        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2:package/C3");

        service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});

        // verify the 3 components per package are enabled (bound)
        verifyExpectedBoundEntries(service, true);

        // verify the last component per package is not enabled/we don't try to bind to it
        for (String pkg : packages) {
            ComponentName unapprovedAdditionalComponent =
                    ComponentName.unflattenFromString(pkg + "/C3");
            assertFalse(
                    service.isComponentEnabledForCurrentProfiles(
                            unapprovedAdditionalComponent));
            verify(mIpm, never()).getServiceInfo(
                    eq(unapprovedAdditionalComponent), anyInt(), anyInt());
        }
    }

    @Test
    public void testSetPackageOrComponentEnabled() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            ArrayMap<Integer, ArrayList<String>> expectedEnabled = new ArrayMap<>();
            expectedEnabled.put(0,
                    Lists.newArrayList(new String[]{"package/Comp", "package/C2", "again/M4"}));
            expectedEnabled.put(10,
                    Lists.newArrayList(new String[]{"user10package/B", "user10/Component",
                            "user10package1/K", "user10.3/Component", "user10package2/L",
                            "user10.4/Component"}));

            for (int userId : expectedEnabled.keySet()) {
                ArrayList<String> expectedForUser = expectedEnabled.get(userId);
                for (int i = 0; i < expectedForUser.size(); i++) {
                    boolean primary = i % 2 == 0;
                    service.setPackageOrComponentEnabled(expectedForUser.get(i), userId, primary,
                            true);
                }
            }

            // verify everything added is approved
            for (int userId : expectedEnabled.keySet()) {
                ArrayList<String> expectedForUser = expectedEnabled.get(userId);
                for (int i = 0; i < expectedForUser.size(); i++) {
                    String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
                            ? expectedForUser.get(i)
                            : service.getPackageName(expectedForUser.get(i));
                    assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue
                            + " for approval level " + approvalLevel,
                            service.isPackageOrComponentAllowed(verifyValue, userId));
                }
            }

            ArrayMap<Integer, ArrayList<String>> expectedNoAccess = new ArrayMap<>();
            for (int userId : expectedEnabled.keySet()) {
                ArrayList<String> expectedForUser = expectedEnabled.get(userId);
                for (int i = expectedForUser.size() - 1; i >= 0; i--) {
                    ArrayList<String> removed = new ArrayList<>();
                    if (i % 3 == 0) {
                        String revokeAccessFor = expectedForUser.remove(i);
                        removed.add(revokeAccessFor);
                        service.setPackageOrComponentEnabled(
                                revokeAccessFor, userId, i % 2 == 0, false);
                    }
                    expectedNoAccess.put(userId, removed);
                }
            }

            // verify everything still there is approved
            for (int userId : expectedEnabled.keySet()) {
                ArrayList<String> expectedForUser = expectedEnabled.get(userId);
                for (int i = 0; i < expectedForUser.size(); i++) {
                    String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
                            ? expectedForUser.get(i)
                            : service.getPackageName(expectedForUser.get(i));
                    assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue,
                            service.isPackageOrComponentAllowed(verifyValue, userId));
                }
            }
            // verify everything removed isn't
            for (int userId : expectedNoAccess.keySet()) {
                ArrayList<String> notExpectedForUser = expectedNoAccess.get(userId);
                for (int i = 0; i < notExpectedForUser.size(); i++) {
                    assertFalse(
                            "Is allowed: user: " + userId + " entry: " + notExpectedForUser.get(i),
                            service.isPackageOrComponentAllowed(notExpectedForUser.get(i), userId));
                }
            }
        }
    }

    @Test
    public void testGetAllowedPackages_byUser() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            loadXml(service);

            List<String> allowedPackagesForUser0 = new ArrayList<>();
            allowedPackagesForUser0.add("this.is.a.package.name");
            allowedPackagesForUser0.add("another.package");
            allowedPackagesForUser0.add("secondary");

            List<String> actual = service.getAllowedPackages(0);
            assertEquals(3, actual.size());
            for (String pkg : allowedPackagesForUser0) {
                assertTrue(actual.contains(pkg));
            }

            List<String> allowedPackagesForUser10 = new ArrayList<>();
            allowedPackagesForUser10.add("this.is.another.package");
            allowedPackagesForUser10.add("package");
            allowedPackagesForUser10.add("this.is.another.package");
            allowedPackagesForUser10.add("component");

            actual = service.getAllowedPackages(10);
            assertEquals(4, actual.size());
            for (String pkg : allowedPackagesForUser10) {
                assertTrue(actual.contains(pkg));
            }
        }
    }

    @Test
    public void testGetAllowedComponentsByUser() throws Exception {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        loadXml(service);

        List<ComponentName> expected = new ArrayList<>();
        expected.add(ComponentName.unflattenFromString("this.is.another.package/M1"));
        expected.add(ComponentName.unflattenFromString("this.is.another.package/with.Component"));
        expected.add(ComponentName.unflattenFromString("component/2"));
        expected.add(ComponentName.unflattenFromString("package/component2"));

        List<ComponentName> actual = service.getAllowedComponents(10);

        assertContentsInAnyOrder(expected, actual);

        assertEquals(expected.size(), actual.size());

        for (ComponentName cn : expected) {
            assertTrue("Actual missing " + cn, actual.contains(cn));
        }

        for (ComponentName cn : actual) {
            assertTrue("Actual contains extra " + cn, expected.contains(cn));
        }
    }

    @Test
    public void testGetAllowedComponents_approvalByPackage() throws Exception {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_PACKAGE);
        loadXml(service);

        assertEquals(0, service.getAllowedComponents(10).size());
    }

    @Test
    public void testGetAllowedPackages() throws Exception {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                mIpm, APPROVAL_BY_COMPONENT);
        loadXml(service);
        service.mApprovalLevel = APPROVAL_BY_PACKAGE;
        loadXml(service);

        List<String> allowedPackages = new ArrayList<>();
        allowedPackages.add("this.is.a.package.name");
        allowedPackages.add("another.package");
        allowedPackages.add("secondary");
        allowedPackages.add("this.is.another.package");
        allowedPackages.add("package");
        allowedPackages.add("component");
        allowedPackages.add("bananas!");

        Set<String> actual = service.getAllowedPackages();
        assertEquals(allowedPackages.size(), actual.size());
        for (String pkg : allowedPackages) {
            assertTrue(actual.contains(pkg));
        }
    }

    @Test
    public void testOnUserRemoved() throws Exception {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            loadXml(service);

            ArrayMap<Integer, String> verifyMap = mExpectedPrimary.get(service.mApprovalLevel);
            String user0 = verifyMap.remove(0);
            verifyMap = mExpectedSecondary.get(service.mApprovalLevel);
            user0 = user0 + ":" + verifyMap.remove(0);

            service.onUserRemoved(0);

            for (String verifyValue : user0.split(":")) {
                if (!TextUtils.isEmpty(verifyValue)) {
                    assertFalse("service type " + service.mApprovalLevel + ":" + verifyValue
                            + " is still allowed",
                            service.isPackageOrComponentAllowed(verifyValue, 0));
                }
            }

            verifyExpectedApprovedEntries(service);
        }
    }

    @Test
    public void testIsSameUser() {
        IInterface service = mock(IInterface.class);
        when(service.asBinder()).thenReturn(mock(IBinder.class));
        ManagedServices services = new TestManagedServices(getContext(), mLock, mUserProfiles,
                mIpm, APPROVAL_BY_PACKAGE);
        services.registerService(service, null, 10);
        ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service);
        info.isSystem = true;

        assertFalse(services.isSameUser(service, 0));
        assertTrue(services.isSameUser(service, 10));
    }

    @Test
    public void testGetAllowedComponents() throws Exception {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        loadXml(service);

        SparseArray<ArraySet<ComponentName>> expected = new SparseArray<>();

        ArraySet<ComponentName> expected10 = new ArraySet<>();
        expected10.add(ComponentName.unflattenFromString("this.is.another.package/M1"));
        expected10.add(ComponentName.unflattenFromString("this.is.another.package/with.Component"));
        expected10.add(ComponentName.unflattenFromString("component/2"));
        expected10.add(ComponentName.unflattenFromString("package/component2"));
        expected.put(10, expected10);
        ArraySet<ComponentName> expected0 = new ArraySet<>();
        expected0.add(ComponentName.unflattenFromString("secondary/component.Name"));
        expected0.add(ComponentName.unflattenFromString("this.is.a.package.name/Ba"));
        expected0.add(ComponentName.unflattenFromString("another.package/B1"));
        expected.put(0, expected0);
        ArraySet<ComponentName> expected12 = new ArraySet<>();
        expected12.add(ComponentName.unflattenFromString("bananas!/Bananas!"));
        expected.put(12, expected12);
        expected.put(11, new ArraySet<>());

        SparseArray<ArraySet<ComponentName>> actual =
                service.getAllowedComponents(mUserProfiles.getCurrentProfileIds());

        assertContentsInAnyOrder(expected, actual);
    }

    @Test
    public void testPopulateComponentsToUnbind_forceRebind() {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);

        IInterface iInterface = mock(IInterface.class);
        when(iInterface.asBinder()).thenReturn(mock(IBinder.class));

        ManagedServices.ManagedServiceInfo service0 = service.new ManagedServiceInfo(
                iInterface, ComponentName.unflattenFromString("a/a"), 0, false,
                mock(ServiceConnection.class), 26);
        ManagedServices.ManagedServiceInfo service10 = service.new ManagedServiceInfo(
                iInterface, ComponentName.unflattenFromString("b/b"), 10, false,
                mock(ServiceConnection.class), 26);
        Set<ManagedServices.ManagedServiceInfo> removableBoundServices = new ArraySet<>();
        removableBoundServices.add(service0);
        removableBoundServices.add(service10);

        SparseArray<Set<ComponentName>> allowedComponentsToBind = new SparseArray<>();
        Set<ComponentName> allowed0 = new ArraySet<>();
        allowed0.add(ComponentName.unflattenFromString("a/a"));
        allowedComponentsToBind.put(0, allowed0);
        Set<ComponentName> allowed10 = new ArraySet<>();
        allowed10.add(ComponentName.unflattenFromString("b/b"));
        allowedComponentsToBind.put(10, allowed10);

        SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();

        service.populateComponentsToUnbind(true, removableBoundServices, allowedComponentsToBind,
                componentsToUnbind);

        assertEquals(2, componentsToUnbind.size());
        assertTrue(componentsToUnbind.get(0).contains(ComponentName.unflattenFromString("a/a")));
        assertTrue(componentsToUnbind.get(10).contains(ComponentName.unflattenFromString("b/b")));
    }

    @Test
    public void testPopulateComponentsToUnbind() {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);

        IInterface iInterface = mock(IInterface.class);
        when(iInterface.asBinder()).thenReturn(mock(IBinder.class));

        ManagedServices.ManagedServiceInfo service0 = service.new ManagedServiceInfo(
                iInterface, ComponentName.unflattenFromString("a/a"), 0, false,
                mock(ServiceConnection.class), 26);
        ManagedServices.ManagedServiceInfo service0a = service.new ManagedServiceInfo(
                iInterface, ComponentName.unflattenFromString("c/c"), 0, false,
                mock(ServiceConnection.class), 26);
        ManagedServices.ManagedServiceInfo service10 = service.new ManagedServiceInfo(
                iInterface, ComponentName.unflattenFromString("b/b"), 10, false,
                mock(ServiceConnection.class), 26);
        Set<ManagedServices.ManagedServiceInfo> removableBoundServices = new ArraySet<>();
        removableBoundServices.add(service0);
        removableBoundServices.add(service0a);
        removableBoundServices.add(service10);

        SparseArray<Set<ComponentName>> allowedComponentsToBind = new SparseArray<>();
        Set<ComponentName> allowed0 = new ArraySet<>();
        allowed0.add(ComponentName.unflattenFromString("a/a"));
        allowedComponentsToBind.put(0, allowed0);
        Set<ComponentName> allowed10 = new ArraySet<>();
        allowed10.add(ComponentName.unflattenFromString("b/b"));
        allowedComponentsToBind.put(10, allowed10);

        SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();

        service.populateComponentsToUnbind(false, removableBoundServices, allowedComponentsToBind,
                componentsToUnbind);

        assertEquals(1, componentsToUnbind.size());
        assertEquals(1, componentsToUnbind.get(0).size());
        assertTrue(componentsToUnbind.get(0).contains(ComponentName.unflattenFromString("c/c")));
    }

    @Test
    public void populateComponentsToBind() {
        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);

        SparseArray<ArraySet<ComponentName>> approvedComponentsByUser = new SparseArray<>();
        ArraySet<ComponentName> allowed0 = new ArraySet<>();
        allowed0.add(ComponentName.unflattenFromString("a/a"));
        approvedComponentsByUser.put(0, allowed0);
        ArraySet<ComponentName> allowed10 = new ArraySet<>();
        allowed10.add(ComponentName.unflattenFromString("b/b"));
        allowed10.add(ComponentName.unflattenFromString("c/c"));
        approvedComponentsByUser.put(10, allowed10);
        ArraySet<ComponentName> allowed15 = new ArraySet<>();
        allowed15.add(ComponentName.unflattenFromString("d/d"));
        approvedComponentsByUser.put(15, allowed15);

        IntArray users = new IntArray();
        users.add(10);
        users.add(0);

        SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();

        service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser);

        assertEquals(2, componentsToBind.size());
        assertEquals(1, componentsToBind.get(0).size());
        assertTrue(componentsToBind.get(0).contains(ComponentName.unflattenFromString("a/a")));
        assertEquals(2, componentsToBind.get(10).size());
        assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("b/b")));
        assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("c/c")));
    }

    @Test
    public void testOnNullBinding() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        service.registerSystemService(cn, 0);
        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onNullBinding(cn);
            return true;
        });

        service.registerSystemService(cn, 0);
        assertFalse(service.isBound(cn, 0));
    }

    @Test
    public void testOnServiceConnected() throws Exception {
        Context context = mock(Context.class);
        PackageManager pm = mock(PackageManager.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;

        when(context.getPackageName()).thenReturn(mContext.getPackageName());
        when(context.getUserId()).thenReturn(mContext.getUserId());
        when(context.getPackageManager()).thenReturn(pm);
        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);

        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
                APPROVAL_BY_COMPONENT);
        ComponentName cn = ComponentName.unflattenFromString("a/a");

        service.registerSystemService(cn, 0);
        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            ServiceConnection sc = (ServiceConnection) args[1];
            sc.onServiceConnected(cn, mock(IBinder.class));
            return true;
        });

        service.registerSystemService(cn, 0);
        assertTrue(service.isBound(cn, 0));
    }

    @Test
    public void testOnPackagesChanged_nullValuesPassed_noNullPointers() {
        for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
            ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
                    mIpm, approvalLevel);
            // null uid list
            service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, null);

            // null package list
            service.onPackagesChanged(true, null, new int[]{103});
        }
    }

    @Test
    public void loadDefaults_noVersionNoDefaults() throws Exception {
        resetComponentsAndPackages();
        loadXml(mService);
        assertEquals(mService.getDefaultComponents().size(), 0);
    }

    @Test
    public void loadDefaults_noVersionNoDefaultsOneActive() throws Exception {
        resetComponentsAndPackages();
        mService.addDefaultComponentOrPackage("package/class");
        loadXml(mService);
        assertEquals(1, mService.getDefaultComponents().size());
        assertTrue(mService.getDefaultComponents()
                .contains(ComponentName.unflattenFromString("package/class")));
    }

    @Test
    public void loadDefaults_noVersionWithDefaults() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(), mDefaults);
    }

    @Test
    public void loadDefaults_versionOneWithDefaultsWithActive() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mExpectedPrimaryComponentNames.put(0, "package/class");
        mVersionString = "1";
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(),
                new ArraySet(Arrays.asList(new ComponentName("package", "class"))));
    }

    @Test
    public void loadDefaults_versionTwoWithDefaultsWithActive() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mDefaultsString = "default/class";
        mExpectedPrimaryComponentNames.put(0, "package/class");
        mVersionString = "2";
        loadXml(mService);
        assertEquals(1, mService.getDefaultComponents().size());
        mDefaults.forEach(pkg -> {
            assertTrue(mService.getDefaultComponents().contains(pkg));
        });
    }

    @Test
    public void loadDefaults_versionOneWithXMLDefaultsWithActive() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mDefaultsString = "xml/class";
        mExpectedPrimaryComponentNames.put(0, "package/class");
        mVersionString = "1";
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(),
                new ArraySet(Arrays.asList(new ComponentName("xml", "class"))));
    }

    @Test
    public void loadDefaults_versionTwoWithXMLDefaultsWithActive() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mDefaultsString = "xml/class";
        mExpectedPrimaryComponentNames.put(0, "package/class");
        mVersionString = "2";
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(),
                new ArraySet(Arrays.asList(new ComponentName("xml", "class"))));
    }

    private void resetComponentsAndPackages() {
        ArrayMap<Integer, ArrayMap<Integer, String>> empty = new ArrayMap(1);
        ArrayMap<Integer, String> emptyPkgs = new ArrayMap(0);
        empty.append(mService.mApprovalLevel, emptyPkgs);
        mExpectedPrimary = empty;
        mExpectedPrimaryComponentNames = emptyPkgs;
        mExpectedPrimaryPackages = emptyPkgs;
        mExpectedSecondary = empty;
        mExpectedSecondaryComponentNames = emptyPkgs;
        mExpectedSecondaryPackages = emptyPkgs;
    }

    private void loadXml(ManagedServices service) throws Exception {
        final StringBuffer xml = new StringBuffer();
        String xmlTag = service.getConfig().xmlTag;
        xml.append("<" + xmlTag
                + (mDefaultsString != null ? " defaults=\"" + mDefaultsString + "\" " : "")
                + (mVersionString != null ? " version=\"" + mVersionString + "\" " : "")
                + ">\n");
        for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) {
            xml.append(getXmlEntry(
                    mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true));
        }
        for (int userId : mExpectedSecondary.get(service.mApprovalLevel).keySet()) {
            xml.append(getXmlEntry(
                    mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false));
        }
        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                        + ManagedServices.ATT_USER_ID + "=\"99\" "
                        + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
                        + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n");
        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                + ManagedServices.ATT_USER_ID + "=\"98\" "
                + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
                + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
        xml.append("</" + xmlTag + ">");

        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(new BufferedInputStream(
                new ByteArrayInputStream(xml.toString().getBytes())), null);
        parser.nextTag();
        service.readXml(parser, null, false, UserHandle.USER_ALL);
    }

    private XmlPullParser getParserWithEntries(ManagedServices service, String... xmlEntries)
            throws Exception {
        final StringBuffer xml = new StringBuffer();
        xml.append("<" + service.getConfig().xmlTag + ">\n");
        for (String xmlEntry : xmlEntries) {
            xml.append(xmlEntry);
        }
        xml.append("</" + service.getConfig().xmlTag + ">");

        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(new BufferedInputStream(
                new ByteArrayInputStream(xml.toString().getBytes())), null);
        parser.nextTag();
        return parser;
    }

    private void addExpectedServices(final ManagedServices service, final List<String> packages,
            int userId) {
        ManagedServices.Config config = service.getConfig();
        when(mPm.queryIntentServicesAsUser(any(), anyInt(), eq(userId))).
                thenAnswer(new Answer<List<ResolveInfo>>() {
                    @Override
                    public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
                            throws Throwable {
                        Object[] args = invocationOnMock.getArguments();
                        Intent invocationIntent = (Intent) args[0];
                        if (invocationIntent != null) {
                            if (invocationIntent.getAction().equals(
                                    config.serviceInterface)
                                    && packages.contains(invocationIntent.getPackage())) {
                                List<ResolveInfo> dummyServices = new ArrayList<>();
                                for (int i = 1; i <= 3; i ++) {
                                    ResolveInfo resolveInfo = new ResolveInfo();
                                    ServiceInfo serviceInfo = new ServiceInfo();
                                    serviceInfo.packageName = invocationIntent.getPackage();
                                    serviceInfo.name = "C"+i;
                                    serviceInfo.permission = service.getConfig().bindPermission;
                                    resolveInfo.serviceInfo = serviceInfo;
                                    dummyServices.add(resolveInfo);
                                }
                                return dummyServices;
                            }
                        }
                        return new ArrayList<>();
                    }
                });
    }

    private List<String> stringToList(String list) {
        if (list == null) {
            list = "";
        }
        return new ArrayList<>(Lists.newArrayList(list.split(
                ManagedServices.ENABLED_SERVICES_SEPARATOR)));
    }

    private void assertContentsInAnyOrder(Collection<?> expected, Collection<?> actual) {
        assertNotNull(actual);
        assertEquals(expected.size(), actual.size());

        for (Object o : expected) {
            assertTrue("Actual missing " + o, actual.contains(o));
        }

        for (Object o : actual) {
            assertTrue("Actual contains extra " + o, expected.contains(o));
        }
    }

    private void assertContentsInAnyOrder(SparseArray<ArraySet<ComponentName>> expected,
            SparseArray<ArraySet<ComponentName>> actual) throws Exception {
        assertEquals(expected.size(), actual.size());

        for (int i = 0; i < expected.size(); i++) {
            int key = expected.keyAt(i);
            assertTrue(actual.indexOfKey(key) >= 0);
            try {
                assertContentsInAnyOrder(expected.valueAt(i), actual.get(key));
            } catch (Throwable t) {
                throw new Exception("Error validating " + key, t);
            }
        }
    }

    private void verifyExpectedBoundEntries(ManagedServices service, boolean primary)
            throws Exception {
        ArrayMap<Integer, String> verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel)
                : mExpectedSecondary.get(service.mApprovalLevel);
        for (int userId : verifyMap.keySet()) {
            for (String packageOrComponent : verifyMap.get(userId).split(":")) {
                if (!TextUtils.isEmpty(packageOrComponent)) {
                    if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) {
                        assertTrue(packageOrComponent,
                                service.isComponentEnabledForPackage(packageOrComponent));
                        for (int i = 1; i <= 3; i++) {
                            ComponentName componentName = ComponentName.unflattenFromString(
                                    packageOrComponent +"/C" + i);
                            assertTrue(service.isComponentEnabledForCurrentProfiles(
                                    componentName));
                            verify(mIpm, times(1)).getServiceInfo(
                                    eq(componentName), anyInt(), anyInt());
                        }
                    } else {
                        ComponentName componentName =
                                ComponentName.unflattenFromString(packageOrComponent);
                        assertTrue(service.isComponentEnabledForCurrentProfiles(componentName));
                        verify(mIpm, times(1)).getServiceInfo(
                                eq(componentName), anyInt(), anyInt());
                    }
                }
            }
        }
    }

    private void verifyExpectedApprovedEntries(ManagedServices service) {
        verifyExpectedApprovedEntries(service, true);
        verifyExpectedApprovedEntries(service, false);
    }

    private void verifyExpectedApprovedEntries(ManagedServices service, boolean primary) {
        ArrayMap<Integer, String> verifyMap = primary
                ? mExpectedPrimary.get(service.mApprovalLevel)
                : mExpectedSecondary.get(service.mApprovalLevel);
        verifyExpectedApprovedEntries(service, verifyMap);
    }

    private void verifyExpectedApprovedEntries(ManagedServices service,
            ArrayMap<Integer, String> verifyMap) {
        for (int userId : verifyMap.keySet()) {
            for (String verifyValue : verifyMap.get(userId).split(":")) {
                if (!TextUtils.isEmpty(verifyValue)) {
                    assertTrue("service type " + service.mApprovalLevel + ":"
                                    + verifyValue + " is not allowed for user " + userId,
                            service.isPackageOrComponentAllowed(verifyValue, userId));
                }
            }
        }
    }


    private void verifyExpectedApprovedPackages(ManagedServices service) {
        verifyExpectedApprovedPackages(service, true);
        verifyExpectedApprovedPackages(service, false);
    }

    private void verifyExpectedApprovedPackages(ManagedServices service, boolean primary) {
        ArrayMap<Integer, String> verifyMap = primary
                ? mExpectedPrimary.get(service.mApprovalLevel)
                : mExpectedSecondary.get(service.mApprovalLevel);
        verifyExpectedApprovedPackages(service, verifyMap);
    }

    private void verifyExpectedApprovedPackages(ManagedServices service,
            ArrayMap<Integer, String> verifyMap) {
        for (int userId : verifyMap.keySet()) {
            for (String verifyValue : verifyMap.get(userId).split(":")) {
                if (!TextUtils.isEmpty(verifyValue)) {
                    ComponentName component = ComponentName.unflattenFromString(verifyValue);
                    if (component != null ) {
                        assertTrue("service type " + service.mApprovalLevel + ":"
                                        + verifyValue + " is not allowed for user " + userId,
                                service.isPackageAllowed(component.getPackageName(), userId));
                    } else {
                        assertTrue("service type " + service.mApprovalLevel + ":"
                                        + verifyValue + " is not allowed for user " + userId,
                                service.isPackageAllowed(verifyValue, userId));
                    }
                }
            }
        }
    }

    private void writeExpectedValuesToSettings(int approvalLevel) {
        for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
            Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING,
                    mExpectedPrimary.get(approvalLevel).get(userId), userId);
        }
        for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
            Settings.Secure.putStringForUser(getContext().getContentResolver(), SECONDARY_SETTING,
                    mExpectedSecondary.get(approvalLevel).get(userId), userId);
        }
    }

    private String getXmlEntry(String approved, int userId, boolean isPrimary) {
        return "<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                + ManagedServices.ATT_USER_ID + "=\"" + userId +"\" "
                + ManagedServices.ATT_IS_PRIMARY + "=\"" + isPrimary +"\" "
                + ManagedServices.ATT_APPROVED_LIST + "=\"" + approved +"\" "
                + "/>\n";
    }

    class TestManagedServices extends ManagedServices {

        public TestManagedServices(Context context, Object mutex, UserProfiles userProfiles,
                IPackageManager pm, int approvedServiceType) {
            super(context, mutex, userProfiles, pm);
            mApprovalLevel = approvedServiceType;
        }

        @Override
        protected Config getConfig() {
            final Config c = new Config();
            c.xmlTag = "test";
            c.secureSettingName = SETTING;
            c.secondarySettingName = SECONDARY_SETTING;
            c.bindPermission = "permission";
            c.serviceInterface = "serviceInterface";
            return c;
        }

        @Override
        protected IInterface asInterface(IBinder binder) {
            return null;
        }

        @Override
        protected boolean checkType(IInterface service) {
            return true;
        }

        @Override
        protected void onServiceAdded(ManagedServiceInfo info) {

        }

        @Override
        protected void loadDefaultsFromConfig() {
            mDefaultComponents.addAll(mDefaults);
        }

        @Override
        protected String getRequiredPermission() {
            return null;
        }
    }
}
