Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.server.notification;
     17 
     18 import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
     19 import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
     20 
     21 import static junit.framework.Assert.assertEquals;
     22 import static junit.framework.Assert.assertFalse;
     23 import static junit.framework.Assert.assertTrue;
     24 
     25 import static org.mockito.Matchers.any;
     26 import static org.mockito.Matchers.anyInt;
     27 import static org.mockito.Matchers.eq;
     28 import static org.mockito.Mockito.never;
     29 import static org.mockito.Mockito.times;
     30 import static org.mockito.Mockito.verify;
     31 import static org.mockito.Mockito.when;
     32 
     33 import android.content.ComponentName;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.pm.IPackageManager;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.ResolveInfo;
     39 import android.content.pm.ServiceInfo;
     40 import android.content.pm.UserInfo;
     41 import android.os.Build;
     42 import android.os.IBinder;
     43 import android.os.IInterface;
     44 import android.os.UserHandle;
     45 import android.os.UserManager;
     46 import android.provider.Settings;
     47 import android.text.TextUtils;
     48 import android.util.ArrayMap;
     49 import android.util.Xml;
     50 
     51 import com.android.internal.util.FastXmlSerializer;
     52 import com.android.server.UiServiceTestCase;
     53 
     54 import com.google.android.collect.Lists;
     55 
     56 import org.junit.Before;
     57 import org.junit.Test;
     58 import org.mockito.Mock;
     59 import org.mockito.MockitoAnnotations;
     60 import org.mockito.invocation.InvocationOnMock;
     61 import org.mockito.stubbing.Answer;
     62 import org.xmlpull.v1.XmlPullParser;
     63 import org.xmlpull.v1.XmlSerializer;
     64 
     65 import java.io.BufferedInputStream;
     66 import java.io.BufferedOutputStream;
     67 import java.io.ByteArrayInputStream;
     68 import java.io.ByteArrayOutputStream;
     69 import java.util.ArrayList;
     70 import java.util.List;
     71 
     72 public class ManagedServicesTest extends UiServiceTestCase {
     73 
     74     @Mock
     75     private IPackageManager mIpm;
     76     @Mock
     77     private PackageManager mPm;
     78     @Mock
     79     private UserManager mUm;
     80     @Mock
     81     private ManagedServices.UserProfiles mUserProfiles;
     82     Object mLock = new Object();
     83 
     84     UserInfo mZero = new UserInfo(0, "zero", 0);
     85     UserInfo mTen = new UserInfo(10, "ten", 0);
     86 
     87     private static final String SETTING = "setting";
     88     private static final String SECONDARY_SETTING = "secondary_setting";
     89 
     90     private ArrayMap<Integer, String> mExpectedPrimaryPackages;
     91     private ArrayMap<Integer, String> mExpectedPrimaryComponentNames;
     92     private ArrayMap<Integer, String> mExpectedSecondaryPackages;
     93     private ArrayMap<Integer, String> mExpectedSecondaryComponentNames;
     94 
     95     // type : user : list of approved
     96     private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary = new ArrayMap<>();
     97     private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary = new ArrayMap<>();
     98 
     99     @Before
    100     public void setUp() throws Exception {
    101         MockitoAnnotations.initMocks(this);
    102 
    103         getContext().setMockPackageManager(mPm);
    104         getContext().addMockSystemService(Context.USER_SERVICE, mUm);
    105 
    106         List<UserInfo> users = new ArrayList<>();
    107         users.add(mZero);
    108         users.add(mTen);
    109         users.add(new UserInfo(11, "11", 0));
    110         users.add(new UserInfo(12, "12", 0));
    111         for (UserInfo user : users) {
    112             when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
    113         }
    114         when(mUm.getUsers()).thenReturn(users);
    115         when(mUserProfiles.getCurrentProfileIds()).thenReturn(new int[] {0, 10, 11, 12});
    116 
    117         mExpectedPrimaryPackages = new ArrayMap<>();
    118         mExpectedPrimaryPackages.put(0, "this.is.a.package.name:another.package");
    119         mExpectedPrimaryPackages.put(10, "this.is.another.package");
    120         mExpectedPrimaryPackages.put(11, "");
    121         mExpectedPrimaryPackages.put(12, "bananas!");
    122         mExpectedPrimaryComponentNames = new ArrayMap<>();
    123         mExpectedPrimaryComponentNames.put(0, "this.is.a.package.name/Ba:another.package/B1");
    124         mExpectedPrimaryComponentNames.put(10, "this.is.another.package/M1");
    125         mExpectedPrimaryComponentNames.put(11, "");
    126         mExpectedPrimaryComponentNames.put(12, "bananas!/Bananas!");
    127         mExpectedPrimary.put(APPROVAL_BY_PACKAGE, mExpectedPrimaryPackages);
    128         mExpectedPrimary.put(APPROVAL_BY_COMPONENT, mExpectedPrimaryComponentNames);
    129 
    130         mExpectedSecondaryComponentNames = new ArrayMap<>();
    131         mExpectedSecondaryComponentNames.put(0, "secondary/component.Name");
    132         mExpectedSecondaryComponentNames.put(10,
    133                 "this.is.another.package/with.Component:component/2:package/component2");
    134         mExpectedSecondaryPackages = new ArrayMap<>();
    135         mExpectedSecondaryPackages.put(0, "secondary");
    136         mExpectedSecondaryPackages.put(10,
    137                 "this.is.another.package:component:package");
    138         mExpectedSecondary.put(APPROVAL_BY_PACKAGE, mExpectedSecondaryPackages);
    139         mExpectedSecondary.put(APPROVAL_BY_COMPONENT, mExpectedSecondaryComponentNames);
    140     }
    141 
    142     @Test
    143     public void testBackupAndRestore_migration() throws Exception {
    144         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    145             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    146                     mIpm, approvalLevel);
    147 
    148             for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
    149                 service.onSettingRestored(
    150                         service.getConfig().secureSettingName,
    151                         mExpectedPrimary.get(approvalLevel).get(userId),
    152                         Build.VERSION_CODES.O, userId);
    153             }
    154             verifyExpectedApprovedEntries(service, true);
    155 
    156             for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
    157                 service.onSettingRestored(service.getConfig().secondarySettingName,
    158                         mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
    159                         userId);
    160             }
    161             verifyExpectedApprovedEntries(service);
    162         }
    163     }
    164 
    165     @Test
    166     public void testBackupAndRestore_migration_preO() throws Exception {
    167         ArrayMap backupPrimaryPackages = new ArrayMap<>();
    168         backupPrimaryPackages.put(0, "backup.0:backup:0a");
    169         backupPrimaryPackages.put(10, "10.backup");
    170         backupPrimaryPackages.put(11, "eleven");
    171         backupPrimaryPackages.put(12, "");
    172         ArrayMap backupPrimaryComponentNames = new ArrayMap<>();
    173         backupPrimaryComponentNames.put(0, "backup.first/whatever:a/b");
    174         backupPrimaryComponentNames.put(10, "again/M1");
    175         backupPrimaryComponentNames.put(11, "orange/youglad:itisnot/banana");
    176         backupPrimaryComponentNames.put(12, "");
    177         ArrayMap<Integer, ArrayMap<Integer, String>> backupPrimary = new ArrayMap<>();
    178         backupPrimary.put(APPROVAL_BY_PACKAGE, backupPrimaryPackages);
    179         backupPrimary.put(APPROVAL_BY_COMPONENT, backupPrimaryComponentNames);
    180 
    181         ArrayMap backupSecondaryComponentNames = new ArrayMap<>();
    182         backupSecondaryComponentNames.put(0, "secondary.1/component.Name");
    183         backupSecondaryComponentNames.put(10,
    184                 "this.is.another.package.backup/with.Component:component.backup/2");
    185         ArrayMap backupSecondaryPackages = new ArrayMap<>();
    186         backupSecondaryPackages.put(0, "");
    187         backupSecondaryPackages.put(10,
    188                 "this.is.another.package.backup:package.backup");
    189         ArrayMap<Integer, ArrayMap<Integer, String>> backupSecondary = new ArrayMap<>();
    190         backupSecondary.put(APPROVAL_BY_PACKAGE, backupSecondaryPackages);
    191         backupSecondary.put(APPROVAL_BY_COMPONENT, backupSecondaryComponentNames);
    192 
    193         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    194             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    195                     mIpm, approvalLevel);
    196 
    197             // not an expected flow but a way to get data into the settings
    198             for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
    199                 service.onSettingRestored(
    200                         service.getConfig().secureSettingName,
    201                         mExpectedPrimary.get(approvalLevel).get(userId),
    202                         Build.VERSION_CODES.O, userId);
    203             }
    204 
    205             for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
    206                 service.onSettingRestored(service.getConfig().secondarySettingName,
    207                         mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
    208                         userId);
    209             }
    210 
    211             // actual test
    212             for (int userId : backupPrimary.get(approvalLevel).keySet()) {
    213                 service.onSettingRestored(
    214                         service.getConfig().secureSettingName,
    215                         backupPrimary.get(approvalLevel).get(userId),
    216                         Build.VERSION_CODES.N_MR1, userId);
    217             }
    218             verifyExpectedApprovedEntries(service, true);
    219 
    220             for (int userId : backupSecondary.get(approvalLevel).keySet()) {
    221                 service.onSettingRestored(service.getConfig().secondarySettingName,
    222                         backupSecondary.get(approvalLevel).get(userId),
    223                         Build.VERSION_CODES.N_MR1, userId);
    224             }
    225             verifyExpectedApprovedEntries(service);
    226             verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel));
    227             verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel));
    228         }
    229     }
    230 
    231     @Test
    232     public void testReadXml_migrationFromSettings() throws Exception {
    233         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    234             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    235                     mIpm, approvalLevel);
    236 
    237             // approved services aren't in xml
    238             XmlPullParser parser = Xml.newPullParser();
    239             parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})),
    240                     null);
    241             writeExpectedValuesToSettings(approvalLevel);
    242 
    243             service.migrateToXml();
    244 
    245             verifyExpectedApprovedEntries(service);
    246         }
    247     }
    248 
    249     @Test
    250     public void testReadXml() throws Exception {
    251         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    252             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    253                     mIpm, approvalLevel);
    254 
    255             loadXml(service);
    256 
    257             verifyExpectedApprovedEntries(service);
    258 
    259             int[] invalidUsers = new int[] {98, 99};
    260             for (int invalidUser : invalidUsers) {
    261                 assertFalse("service type " + service.mApprovalLevel + ":"
    262                                 + invalidUser + " is allowed for user " + invalidUser,
    263                         service.isPackageOrComponentAllowed(
    264                                 String.valueOf(invalidUser), invalidUser));
    265             }
    266         }
    267     }
    268 
    269     @Test
    270     public void testReadXml_appendsListOfApprovedComponents() throws Exception {
    271         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    272             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    273                     mIpm, approvalLevel);
    274 
    275             String preApprovedPackage = "some.random.package";
    276             String preApprovedComponent = "some.random.package/C1";
    277 
    278             List<String> packages = new ArrayList<>();
    279             packages.add(preApprovedPackage);
    280             addExpectedServices(service, packages, 0);
    281 
    282             service.setPackageOrComponentEnabled(preApprovedComponent, 0, true, true);
    283 
    284             loadXml(service);
    285 
    286             verifyExpectedApprovedEntries(service);
    287 
    288             String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
    289                     ? preApprovedComponent
    290                     : preApprovedPackage;
    291             assertTrue(service.isPackageOrComponentAllowed(verifyValue, 0));
    292         }
    293     }
    294 
    295     @Test
    296     public void testWriteXml_trimsMissingServices() throws Exception {
    297         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    298             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    299                     mIpm, approvalLevel);
    300             loadXml(service);
    301 
    302             // remove missing
    303             mExpectedPrimaryPackages.put(0, "another.package");
    304             mExpectedPrimaryPackages.remove(12);
    305             mExpectedPrimaryComponentNames.put(0, "another.package/B1");
    306             mExpectedPrimaryComponentNames.remove(12);
    307             mExpectedSecondaryPackages.put(10, "this.is.another.package:component");
    308             mExpectedSecondaryComponentNames.put(
    309                     10, "this.is.another.package/with.Component:component/2");
    310 
    311             for (UserInfo userInfo : mUm.getUsers()) {
    312                 List<String> entriesExpectedToHaveServices = new ArrayList<>();
    313                 if (mExpectedPrimary.get(approvalLevel).containsKey(userInfo.id)) {
    314                     for (String packageOrComponent :
    315                             mExpectedPrimary.get(approvalLevel).get(userInfo.id).split(":")) {
    316                         if (!TextUtils.isEmpty(packageOrComponent)) {
    317                             entriesExpectedToHaveServices.add(
    318                                     service.getPackageName(packageOrComponent));
    319                         }
    320                     }
    321                 }
    322                 if (mExpectedSecondary.get(approvalLevel).containsKey(userInfo.id)) {
    323                     for (String packageOrComponent :
    324                             mExpectedSecondary.get(approvalLevel).get(userInfo.id).split(":")) {
    325                         if (!TextUtils.isEmpty(packageOrComponent)) {
    326                             entriesExpectedToHaveServices.add(
    327                                     service.getPackageName(packageOrComponent));
    328                         }
    329                     }
    330                 }
    331                 addExpectedServices(service, entriesExpectedToHaveServices, userInfo.id);
    332             }
    333 
    334             XmlSerializer serializer = new FastXmlSerializer();
    335             ByteArrayOutputStream baos = new ByteArrayOutputStream();
    336             serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
    337             serializer.startDocument(null, true);
    338             service.writeXml(serializer, true);
    339             serializer.endDocument();
    340             serializer.flush();
    341 
    342             XmlPullParser parser = Xml.newPullParser();
    343             parser.setInput(new BufferedInputStream(
    344                     new ByteArrayInputStream(baos.toByteArray())), null);
    345             parser.nextTag();
    346             service.readXml(parser, null);
    347 
    348             verifyExpectedApprovedEntries(service);
    349             assertFalse(service.isPackageOrComponentAllowed("this.is.a.package.name", 0));
    350             assertFalse(service.isPackageOrComponentAllowed("bananas!", 12));
    351             assertFalse(service.isPackageOrComponentAllowed("package/component2", 10));
    352         }
    353     }
    354 
    355     @Test
    356     public void testWriteXml_writesSetting() throws Exception {
    357         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    358             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    359                     mIpm, approvalLevel);
    360             loadXml(service);
    361 
    362             XmlSerializer serializer = new FastXmlSerializer();
    363             ByteArrayOutputStream baos = new ByteArrayOutputStream();
    364             serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
    365             serializer.startDocument(null, true);
    366             service.writeXml(serializer, false);
    367             serializer.endDocument();
    368             serializer.flush();
    369 
    370             for (int userId : mUserProfiles.getCurrentProfileIds()) {
    371                 List<String> expected =
    372                         stringToList(mExpectedPrimary.get(approvalLevel).get(userId));
    373                 List<String> actual = stringToList(Settings.Secure.getStringForUser(
    374                         getContext().getContentResolver(),
    375                         service.getConfig().secureSettingName, userId));
    376                 assertContentsInAnyOrder(actual, expected);
    377             }
    378         }
    379     }
    380 
    381     @Test
    382     public void rebindServices_onlyBindsExactMatchesIfComponent() throws Exception {
    383         // If the primary and secondary lists contain component names, only those components within
    384         // the package should be matched
    385         ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    386                 mIpm,
    387                 ManagedServices.APPROVAL_BY_COMPONENT);
    388 
    389         List<String> packages = new ArrayList<>();
    390         packages.add("package");
    391         packages.add("anotherPackage");
    392         addExpectedServices(service, packages, 0);
    393 
    394         // only 2 components are approved per package
    395         mExpectedPrimaryComponentNames.clear();
    396         mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
    397         mExpectedSecondaryComponentNames.clear();
    398         mExpectedSecondaryComponentNames.put(0, "anotherPackage/C1:anotherPackage/C2");
    399 
    400         loadXml(service);
    401 
    402         // verify the 2 components per package are enabled (bound)
    403         verifyExpectedBoundEntries(service, true);
    404         verifyExpectedBoundEntries(service, false);
    405 
    406         // verify the last component per package is not enabled/we don't try to bind to it
    407         for (String pkg : packages) {
    408             ComponentName unapprovedAdditionalComponent =
    409                     ComponentName.unflattenFromString(pkg + "/C3");
    410             assertFalse(
    411                     service.isComponentEnabledForCurrentProfiles(
    412                             unapprovedAdditionalComponent));
    413             verify(mIpm, never()).getServiceInfo(
    414                     eq(unapprovedAdditionalComponent), anyInt(), anyInt());
    415         }
    416     }
    417 
    418     @Test
    419     public void rebindServices_bindsEverythingInAPackage() throws Exception {
    420         // If the primary and secondary lists contain packages, all components within those packages
    421         // should be bound
    422         ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
    423                 APPROVAL_BY_PACKAGE);
    424 
    425         List<String> packages = new ArrayList<>();
    426         packages.add("package");
    427         packages.add("packagea");
    428         addExpectedServices(service, packages, 0);
    429 
    430         // 2 approved packages
    431         mExpectedPrimaryPackages.clear();
    432         mExpectedPrimaryPackages.put(0, "package");
    433         mExpectedSecondaryPackages.clear();
    434         mExpectedSecondaryPackages.put(0, "packagea");
    435 
    436         loadXml(service);
    437 
    438         // verify the 3 components per package are enabled (bound)
    439         verifyExpectedBoundEntries(service, true);
    440         verifyExpectedBoundEntries(service, false);
    441     }
    442 
    443     @Test
    444     public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception {
    445         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    446             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    447                     mIpm, approvalLevel);
    448             writeExpectedValuesToSettings(approvalLevel);
    449             service.migrateToXml();
    450 
    451             mExpectedPrimaryPackages.put(0, "another.package");
    452             mExpectedPrimaryComponentNames.put(0, "another.package/B1");
    453             service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, new int[]{103});
    454 
    455             verifyExpectedApprovedEntries(service);
    456         }
    457     }
    458 
    459     @Test
    460     public void testPackageUninstall_componentNoLongerInApprovedList() throws Exception {
    461         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    462             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    463                     mIpm, approvalLevel);
    464             writeExpectedValuesToSettings(approvalLevel);
    465             service.migrateToXml();
    466 
    467             mExpectedSecondaryComponentNames.put(10, "component/2");
    468             mExpectedSecondaryPackages.put(10, "component");
    469             service.onPackagesChanged(true, new String[]{"this.is.another.package"}, new int[]{
    470                     UserHandle.PER_USER_RANGE + 1});
    471 
    472             verifyExpectedApprovedEntries(service);
    473         }
    474     }
    475 
    476     @Test
    477     public void testSetPackageOrComponentEnabled() throws Exception {
    478         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    479             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    480                     mIpm, approvalLevel);
    481             ArrayMap<Integer, ArrayList<String>> expectedEnabled = new ArrayMap<>();
    482             expectedEnabled.put(0,
    483                     Lists.newArrayList(new String[]{"package/Comp", "package/C2", "again/M4"}));
    484             expectedEnabled.put(10,
    485                     Lists.newArrayList(new String[]{"user10package/B", "user10/Component",
    486                             "user10package1/K", "user10.3/Component", "user10package2/L",
    487                             "user10.4/Component"}));
    488 
    489             for (int userId : expectedEnabled.keySet()) {
    490                 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
    491                 for (int i = 0; i < expectedForUser.size(); i++) {
    492                     boolean primary = i % 2 == 0;
    493                     service.setPackageOrComponentEnabled(expectedForUser.get(i), userId, primary,
    494                             true);
    495                 }
    496             }
    497 
    498             // verify everything added is approved
    499             for (int userId : expectedEnabled.keySet()) {
    500                 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
    501                 for (int i = 0; i < expectedForUser.size(); i++) {
    502                     String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
    503                             ? expectedForUser.get(i)
    504                             : service.getPackageName(expectedForUser.get(i));
    505                     assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue
    506                             + " for approval level " + approvalLevel,
    507                             service.isPackageOrComponentAllowed(verifyValue, userId));
    508                 }
    509             }
    510 
    511             ArrayMap<Integer, ArrayList<String>> expectedNoAccess = new ArrayMap<>();
    512             for (int userId : expectedEnabled.keySet()) {
    513                 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
    514                 for (int i = expectedForUser.size() - 1; i >= 0; i--) {
    515                     ArrayList<String> removed = new ArrayList<>();
    516                     if (i % 3 == 0) {
    517                         String revokeAccessFor = expectedForUser.remove(i);
    518                         removed.add(revokeAccessFor);
    519                         service.setPackageOrComponentEnabled(
    520                                 revokeAccessFor, userId, i % 2 == 0, false);
    521                     }
    522                     expectedNoAccess.put(userId, removed);
    523                 }
    524             }
    525 
    526             // verify everything still there is approved
    527             for (int userId : expectedEnabled.keySet()) {
    528                 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
    529                 for (int i = 0; i < expectedForUser.size(); i++) {
    530                     String verifyValue  = (approvalLevel == APPROVAL_BY_COMPONENT)
    531                             ? expectedForUser.get(i)
    532                             : service.getPackageName(expectedForUser.get(i));
    533                     assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue,
    534                             service.isPackageOrComponentAllowed(verifyValue, userId));
    535                 }
    536             }
    537             // verify everything removed isn't
    538             for (int userId : expectedNoAccess.keySet()) {
    539                 ArrayList<String> notExpectedForUser = expectedNoAccess.get(userId);
    540                 for (int i = 0; i < notExpectedForUser.size(); i++) {
    541                     assertFalse(
    542                             "Is allowed: user: " + userId + " entry: " + notExpectedForUser.get(i),
    543                             service.isPackageOrComponentAllowed(notExpectedForUser.get(i), userId));
    544                 }
    545             }
    546         }
    547     }
    548 
    549     @Test
    550     public void testGetAllowedPackages() throws Exception {
    551         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    552             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    553                     mIpm, approvalLevel);
    554             loadXml(service);
    555 
    556             List<String> allowedPackagesForUser0 = new ArrayList<>();
    557             allowedPackagesForUser0.add("this.is.a.package.name");
    558             allowedPackagesForUser0.add("another.package");
    559             allowedPackagesForUser0.add("secondary");
    560 
    561             List<String> actual = service.getAllowedPackages(0);
    562             assertEquals(3, actual.size());
    563             for (String pkg : allowedPackagesForUser0) {
    564                 assertTrue(actual.contains(pkg));
    565             }
    566 
    567             List<String> allowedPackagesForUser10 = new ArrayList<>();
    568             allowedPackagesForUser10.add("this.is.another.package");
    569             allowedPackagesForUser10.add("package");
    570             allowedPackagesForUser10.add("this.is.another.package");
    571             allowedPackagesForUser10.add("component");
    572 
    573             actual = service.getAllowedPackages(10);
    574             assertEquals(4, actual.size());
    575             for (String pkg : allowedPackagesForUser10) {
    576                 assertTrue(actual.contains(pkg));
    577             }
    578         }
    579     }
    580 
    581     @Test
    582     public void testGetAllowedComponents() throws Exception {
    583         ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
    584                 APPROVAL_BY_COMPONENT);
    585         loadXml(service);
    586 
    587         List<ComponentName> expected = new ArrayList<>();
    588         expected.add(ComponentName.unflattenFromString("this.is.another.package/M1"));
    589         expected.add(ComponentName.unflattenFromString("this.is.another.package/with.Component"));
    590         expected.add(ComponentName.unflattenFromString("component/2"));
    591         expected.add(ComponentName.unflattenFromString("package/component2"));
    592 
    593         List<ComponentName> actual = service.getAllowedComponents(10);
    594 
    595         assertContentsInAnyOrder(expected, actual);
    596 
    597         assertEquals(expected.size(), actual.size());
    598 
    599         for (ComponentName cn : expected) {
    600             assertTrue("Actual missing " + cn, actual.contains(cn));
    601         }
    602 
    603         for (ComponentName cn : actual) {
    604             assertTrue("Actual contains extra " + cn, expected.contains(cn));
    605         }
    606     }
    607 
    608     @Test
    609     public void testGetAllowedComponents_approvalByPackage() throws Exception {
    610         ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
    611                 APPROVAL_BY_PACKAGE);
    612         loadXml(service);
    613 
    614         assertEquals(0, service.getAllowedComponents(10).size());
    615     }
    616 
    617     @Test
    618     public void testOnUserRemoved() throws Exception {
    619         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
    620             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
    621                     mIpm, approvalLevel);
    622             loadXml(service);
    623 
    624             ArrayMap<Integer, String> verifyMap = mExpectedPrimary.get(service.mApprovalLevel);
    625             String user0 = verifyMap.remove(0);
    626             verifyMap = mExpectedSecondary.get(service.mApprovalLevel);
    627             user0 = user0 + ":" + verifyMap.remove(0);
    628 
    629             service.onUserRemoved(0);
    630 
    631             for (String verifyValue : user0.split(":")) {
    632                 if (!TextUtils.isEmpty(verifyValue)) {
    633                     assertFalse("service type " + service.mApprovalLevel + ":" + verifyValue
    634                             + " is still allowed",
    635                             service.isPackageOrComponentAllowed(verifyValue, 0));
    636                 }
    637             }
    638 
    639             verifyExpectedApprovedEntries(service);
    640         }
    641     }
    642 
    643     private void loadXml(ManagedServices service) throws Exception {
    644         final StringBuffer xml = new StringBuffer();
    645         xml.append("<" + service.getConfig().xmlTag + ">\n");
    646         for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) {
    647             xml.append(getXmlEntry(
    648                     mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true));
    649         }
    650         for (int userId : mExpectedSecondary.get(service.mApprovalLevel).keySet()) {
    651             xml.append(getXmlEntry(
    652                     mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false));
    653         }
    654         xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
    655                         + ManagedServices.ATT_USER_ID + "=\"99\" "
    656                         + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
    657                         + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n");
    658         xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
    659                 + ManagedServices.ATT_USER_ID + "=\"98\" "
    660                 + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
    661                 + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
    662         xml.append("</" + service.getConfig().xmlTag + ">");
    663 
    664         XmlPullParser parser = Xml.newPullParser();
    665         parser.setInput(new BufferedInputStream(
    666                 new ByteArrayInputStream(xml.toString().getBytes())), null);
    667         parser.nextTag();
    668         service.readXml(parser, null);
    669     }
    670 
    671     private void addExpectedServices(final ManagedServices service, final List<String> packages,
    672             int userId) {
    673         when(mPm.queryIntentServicesAsUser(any(), anyInt(), eq(userId))).
    674                 thenAnswer(new Answer<List<ResolveInfo>>() {
    675                     @Override
    676                     public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
    677                             throws Throwable {
    678                         Object[] args = invocationOnMock.getArguments();
    679                         Intent invocationIntent = (Intent) args[0];
    680                         if (invocationIntent != null) {
    681                             if (invocationIntent.getAction().equals(
    682                                     service.getConfig().serviceInterface)
    683                                     && packages.contains(invocationIntent.getPackage())) {
    684                                 List<ResolveInfo> dummyServices = new ArrayList<>();
    685                                 for (int i = 1; i <= 3; i ++) {
    686                                     ResolveInfo resolveInfo = new ResolveInfo();
    687                                     ServiceInfo serviceInfo = new ServiceInfo();
    688                                     serviceInfo.packageName = invocationIntent.getPackage();
    689                                     serviceInfo.name = "C"+i;
    690                                     serviceInfo.permission = service.getConfig().bindPermission;
    691                                     resolveInfo.serviceInfo = serviceInfo;
    692                                     dummyServices.add(resolveInfo);
    693                                 }
    694                                 return dummyServices;
    695                             }
    696                         }
    697                         return new ArrayList<>();
    698                     }
    699                 });
    700     }
    701 
    702     private List<String> stringToList(String list) {
    703         if (list == null) {
    704             list = "";
    705         }
    706         return new ArrayList<>(Lists.newArrayList(list.split(
    707                 ManagedServices.ENABLED_SERVICES_SEPARATOR)));
    708     }
    709 
    710     private void assertContentsInAnyOrder(List<?> expected, List<?> actual) {
    711         assertEquals(expected.size(), actual.size());
    712 
    713         for (Object o : expected) {
    714             assertTrue("Actual missing " + o, actual.contains(o));
    715         }
    716 
    717         for (Object o : actual) {
    718             assertTrue("Actual contains extra " + o, expected.contains(o));
    719         }
    720     }
    721 
    722     private void verifyExpectedBoundEntries(ManagedServices service, boolean primary)
    723             throws Exception {
    724         ArrayMap<Integer, String> verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel)
    725                 : mExpectedSecondary.get(service.mApprovalLevel);
    726         for (int userId : verifyMap.keySet()) {
    727             for (String packageOrComponent : verifyMap.get(userId).split(":")) {
    728                 if (!TextUtils.isEmpty(packageOrComponent)) {
    729                     if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) {
    730                         assertTrue(packageOrComponent,
    731                                 service.isComponentEnabledForPackage(packageOrComponent));
    732                         for (int i = 1; i <= 3; i ++) {
    733                             ComponentName componentName = ComponentName.unflattenFromString(
    734                                     packageOrComponent +"/C" + i);
    735                             assertTrue(service.isComponentEnabledForCurrentProfiles(
    736                                     componentName));
    737                             verify(mIpm, times(1)).getServiceInfo(
    738                                     eq(componentName), anyInt(), anyInt());
    739                         }
    740                     } else {
    741                         ComponentName componentName =
    742                                 ComponentName.unflattenFromString(packageOrComponent);
    743                         assertTrue(service.isComponentEnabledForCurrentProfiles(componentName));
    744                         verify(mIpm, times(1)).getServiceInfo(
    745                                 eq(componentName), anyInt(), anyInt());
    746                     }
    747                 }
    748             }
    749         }
    750     }
    751 
    752     private void verifyExpectedApprovedEntries(ManagedServices service) {
    753         verifyExpectedApprovedEntries(service, true);
    754         verifyExpectedApprovedEntries(service, false);
    755     }
    756 
    757     private void verifyExpectedApprovedEntries(ManagedServices service, boolean primary) {
    758         ArrayMap<Integer, String> verifyMap = primary
    759                 ? mExpectedPrimary.get(service.mApprovalLevel)
    760                 : mExpectedSecondary.get(service.mApprovalLevel);
    761         verifyExpectedApprovedEntries(service, verifyMap);
    762     }
    763 
    764     private void verifyExpectedApprovedEntries(ManagedServices service,
    765             ArrayMap<Integer, String> verifyMap) {
    766         for (int userId : verifyMap.keySet()) {
    767             for (String verifyValue : verifyMap.get(userId).split(":")) {
    768                 if (!TextUtils.isEmpty(verifyValue)) {
    769                     assertTrue("service type " + service.mApprovalLevel + ":"
    770                                     + verifyValue + " is not allowed for user " + userId,
    771                             service.isPackageOrComponentAllowed(verifyValue, userId));
    772                 }
    773             }
    774         }
    775     }
    776 
    777     private void writeExpectedValuesToSettings(int approvalLevel) {
    778         for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
    779             Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING,
    780                     mExpectedPrimary.get(approvalLevel).get(userId), userId);
    781         }
    782         for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
    783             Settings.Secure.putStringForUser(getContext().getContentResolver(), SECONDARY_SETTING,
    784                     mExpectedSecondary.get(approvalLevel).get(userId), userId);
    785         }
    786     }
    787 
    788     private String getXmlEntry(String approved, int userId, boolean isPrimary) {
    789         return "<" + ManagedServices.TAG_MANAGED_SERVICES + " "
    790                 + ManagedServices.ATT_USER_ID + "=\"" + userId +"\" "
    791                 + ManagedServices.ATT_IS_PRIMARY + "=\"" + isPrimary +"\" "
    792                 + ManagedServices.ATT_APPROVED_LIST + "=\"" + approved +"\" "
    793                 + "/>\n";
    794     }
    795 
    796     class TestManagedServices extends ManagedServices {
    797 
    798         public TestManagedServices(Context context, Object mutex, UserProfiles userProfiles,
    799                 IPackageManager pm, int approvedServiceType) {
    800             super(context, mutex, userProfiles, pm);
    801             mApprovalLevel = approvedServiceType;
    802         }
    803 
    804         @Override
    805         protected Config getConfig() {
    806             final Config c = new Config();
    807             c.xmlTag = "test";
    808             c.secureSettingName = SETTING;
    809             c.secondarySettingName = SECONDARY_SETTING;
    810             c.bindPermission = "permission";
    811             c.serviceInterface = "serviceInterface";
    812             return c;
    813         }
    814 
    815         @Override
    816         protected IInterface asInterface(IBinder binder) {
    817             return null;
    818         }
    819 
    820         @Override
    821         protected boolean checkType(IInterface service) {
    822             return false;
    823         }
    824 
    825         @Override
    826         protected void onServiceAdded(ManagedServiceInfo info) {
    827 
    828         }
    829     }
    830 }
    831